public override Expression Visit(Expression expression) { if (expression == null) { return(null); } if (!(expression is NewExpression || expression is MemberInitExpression || expression is EntityShaperExpression)) { // This skips the group parameter from GroupJoin if (expression is ParameterExpression parameter && parameter.Type.IsGenericType && parameter.Type.GetGenericTypeDefinition() == typeof(IEnumerable <>)) { return(parameter); } if (_clientEval) { if (expression is ConstantExpression) { return(expression); } if (expression is ParameterExpression parameterExpression) { return(Expression.Call( _getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type), QueryCompilationContext2.QueryContextParameter, Expression.Constant(parameterExpression.Name))); } var translation = _sqlTranslator.Translate(expression); if (translation == null) { return(base.Visit(expression)); } else { return(_selectExpression.AddToProjection(translation, expression.Type)); } } else { var translation = _sqlTranslator.Translate(expression); if (translation == null) { return(null); } _projectionMapping[_projectionMembers.Peek()] = translation; return(new ProjectionBindingExpression(_selectExpression, _projectionMembers.Peek(), expression.Type)); } } return(base.Visit(expression)); }
private static void LiftOrderBy( SelectExpression innerJoinSelectExpression, SelectExpression targetSelectExpression, TableExpressionBase innerJoinExpression) { var needOrderingChanges = innerJoinSelectExpression.OrderBy .Any(x => x.Expression is SelectExpression || x.Expression.IsAliasWithColumnExpression() || x.Expression.IsAliasWithSelectExpression()); var orderings = innerJoinSelectExpression.OrderBy.ToList(); if (needOrderingChanges) { innerJoinSelectExpression.ClearOrderBy(); } foreach (var ordering in orderings) { var orderingExpression = ordering.Expression; var aliasExpression = ordering.Expression as AliasExpression; if (aliasExpression?.Alias != null) { var columnExpression = aliasExpression.TryGetColumnExpression(); if (columnExpression != null) { orderingExpression = new ColumnExpression( aliasExpression.Alias, columnExpression.Property, columnExpression.Table); } } var index = orderingExpression is SelectExpression ? innerJoinSelectExpression.AddAliasToProjection(innerJoinSelectExpression.Alias + "_" + innerJoinSelectExpression.Projection.Count, orderingExpression) : innerJoinSelectExpression.AddToProjection(orderingExpression); var expression = innerJoinSelectExpression.Projection[index]; if (needOrderingChanges) { innerJoinSelectExpression.AddToOrderBy(new Ordering(expression.TryGetColumnExpression() ?? expression, ordering.OrderingDirection)); } var newExpression = targetSelectExpression.UpdateColumnExpression(expression, innerJoinExpression); targetSelectExpression.AddToOrderBy(new Ordering(newExpression, ordering.OrderingDirection)); } if ((innerJoinSelectExpression.Limit == null) && (innerJoinSelectExpression.Offset == null)) { innerJoinSelectExpression.ClearOrderBy(); } }
internal static SelectExpression WhereAndSelectDatabaseExpressions(AdventureWorks adventureWorks) { QueryCompilationContext compilationContext = adventureWorks.GetService <IQueryCompilationContextFactory>() .Create(async: false); SelectExpression databaseExpression = new SelectExpression( dependencies: new SelectExpressionDependencies(adventureWorks.GetService <IQuerySqlGeneratorFactory>(), adventureWorks.GetService <IRelationalTypeMappingSource>()), queryCompilationContext: (RelationalQueryCompilationContext)compilationContext); MainFromClause querySource = new MainFromClause( itemName: "product", itemType: typeof(Product), fromExpression: Expression.Constant(adventureWorks.ProductCategories)); TableExpression tableExpression = new TableExpression( table: nameof(Product), schema: AdventureWorks.Production, alias: querySource.ItemName, querySource: querySource); databaseExpression.AddTable(tableExpression); IEntityType productEntityType = adventureWorks.Model.FindEntityType(typeof(Product)); IProperty nameProperty = productEntityType.FindProperty(nameof(Product.Name)); ColumnExpression nameColumn = new ColumnExpression( name: nameof(Product.Name), property: nameProperty, tableExpression: tableExpression); databaseExpression.AddToProjection(nameColumn); databaseExpression.AddToPredicate(Expression.GreaterThan( left: new ExplicitCastExpression( operand: new SqlFunctionExpression( functionName: "LEN", returnType: typeof(int), arguments: new Expression[] { nameColumn }), type: typeof(int)), right: Expression.Constant(10))); return(databaseExpression.WriteLine()); }
internal static SelectExpression SelectAndFirstDatabaseExpressions(AdventureWorks adventureWorks) { QueryCompilationContext compilationContext = adventureWorks.GetService <IQueryCompilationContextFactory>() .Create(async: false); SelectExpression selectExpression = new SelectExpression( dependencies: new SelectExpressionDependencies(adventureWorks.GetService <IQuerySqlGeneratorFactory>(), adventureWorks.GetService <IRelationalTypeMappingSource>()), queryCompilationContext: (RelationalQueryCompilationContext)compilationContext); MainFromClause querySource = new MainFromClause( itemName: "product", itemType: typeof(Product), fromExpression: Expression.Constant(adventureWorks.ProductCategories)); TableExpression tableExpression = new TableExpression( table: nameof(Product), schema: AdventureWorks.Production, alias: querySource.ItemName, querySource: querySource); selectExpression.AddTable(tableExpression); IEntityType productEntityType = adventureWorks.Model.FindEntityType(typeof(Product)); IProperty nameProperty = productEntityType.FindProperty(nameof(Product.Name)); selectExpression.AddToProjection(new ColumnExpression( name: nameof(Product.Name), property: nameProperty, tableExpression: tableExpression)); selectExpression.Limit = Expression.Constant(1); return(selectExpression.WriteLine()); }
protected override Expression VisitEntityQueryable(Type elementType) { var relationalQueryCompilationContext = ((RelationalQueryCompilationContext)QueryCompilationContext); var queryMethodInfo = relationalQueryCompilationContext.EnumerableMethodProvider.QueryValues; var entityType = QueryCompilationContext.Model.GetEntityType(elementType); var selectExpression = new SelectExpression(elementType) { TableSource = entityType.StorageName }; _queryModelVisitor._queriesBySource.Add(_querySource, selectExpression); if (_queryModelVisitor.QuerySourceRequiresMaterialization(_querySource)) { foreach (var property in entityType.Properties) { selectExpression.AddToProjection(property); } queryMethodInfo = relationalQueryCompilationContext.EnumerableMethodProvider.QueryEntities .MakeGenericMethod(elementType); } return(Expression.Call( queryMethodInfo, QueryContextParameter, Expression.Constant(new CommandBuilder(selectExpression, relationalQueryCompilationContext)))); }
protected override Expression VisitEntityQueryable(Type elementType) { Check.NotNull(elementType, "elementType"); var queryMethodInfo = RelationalQueryModelVisitor.CreateValueReaderMethodInfo; var entityType = QueryModelVisitor.QueryCompilationContext.Model.GetEntityType(elementType); var selectExpression = new SelectExpression(); var tableName = QueryModelVisitor.QueryCompilationContext.GetTableName(entityType); selectExpression .AddTable( new TableExpression( tableName, QueryModelVisitor.QueryCompilationContext.GetSchema(entityType), _querySource.ItemName.StartsWith("<generated>_") ? tableName.First().ToString().ToLower() : _querySource.ItemName, _querySource)); QueryModelVisitor.AddQuery(_querySource, selectExpression); var queryMethodArguments = new List <Expression> { Expression.Constant(_querySource), EntityQueryModelVisitor.QueryContextParameter, EntityQueryModelVisitor.QuerySourceScopeParameter, _readerParameter }; if (QueryModelVisitor.QuerySourceRequiresMaterialization(_querySource)) { foreach (var property in entityType.Properties) { selectExpression.AddToProjection( QueryModelVisitor.QueryCompilationContext .GetColumnName(property), property, _querySource); } queryMethodInfo = RelationalQueryModelVisitor.CreateEntityMethodInfo.MakeGenericMethod(elementType); queryMethodArguments.Add(Expression.Constant(0)); queryMethodArguments.Add(Expression.Constant(entityType)); queryMethodArguments.Add(Expression.Constant(QueryModelVisitor.QuerySourceRequiresTracking(_querySource))); } return(Expression.Call( QueryModelVisitor.QueryCompilationContext.QueryMethodProvider.QueryMethod .MakeGenericMethod(queryMethodInfo.ReturnType), EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(new CommandBuilder(selectExpression, QueryModelVisitor.QueryCompilationContext)), Expression.Lambda( Expression.Call(queryMethodInfo, queryMethodArguments), _readerParameter))); }
Expression VisitSelectExpression(SelectExpression selectExpression) { base.Visit(selectExpression); if (!RequiresRowNumberPaging(selectExpression)) { return(selectExpression); } var subQuery = selectExpression.PushDownSubquery(); foreach (var projection in subQuery.Projection) { selectExpression.AddToProjection(projection.LiftExpressionFromSubquery(subQuery)); } if (subQuery.OrderBy.Count == 0) { subQuery.AddToOrderBy( new Ordering(new SqlFunctionExpression("@@RowCount", typeof(int)), OrderingDirection.Asc)); } var innerRowNumberExpression = new AliasExpression( RowNumberColumnName + (_counter != 0 ? $"{_counter}" : ""), new RowNumberExpression_SqlServer(subQuery.OrderBy)); _counter++; subQuery.ClearOrderBy(); subQuery.AddToProjection(innerRowNumberExpression, false); var rowNumberReferenceExpression = new ColumnReferenceExpression(innerRowNumberExpression, subQuery); var offset = subQuery.Offset ?? Expression.Constant(0); if (subQuery.Offset != null) { selectExpression.AddToPredicate (Expression.GreaterThan(rowNumberReferenceExpression, offset)); subQuery.Offset = null; } if (subQuery.Limit != null) { var constantValue = (subQuery.Limit as ConstantExpression)?.Value; var offsetValue = (offset as ConstantExpression)?.Value; var limitExpression = constantValue != null && offsetValue != null ? (Expression)Expression.Constant((int)offsetValue + (int)constantValue) : Expression.Add(offset, subQuery.Limit); selectExpression.AddToPredicate( Expression.LessThanOrEqual(rowNumberReferenceExpression, limitExpression)); subQuery.Limit = null; } return(selectExpression); }
private AliasExpression CreateAliasedColumnExpression( IProperty property, IQuerySource querySource, SelectExpression selectExpression) { if (_targetSelectExpression != null && selectExpression != _targetSelectExpression) { selectExpression?.AddToProjection( _relationalAnnotationProvider.For(property).ColumnName, property, querySource); return(null); } return(CreateAliasedColumnExpressionCore(property, querySource, selectExpression)); }
private AliasExpression CreateAliasedColumnExpression( IProperty property, IQuerySource querySource, SelectExpression selectExpression) { if (_targetSelectExpression != null && selectExpression != _targetSelectExpression) { selectExpression?.AddToProjection( _queryModelVisitor.QueryCompilationContext.RelationalExtensions.For(property).ColumnName, property, querySource); return(null); } return(CreateAliasedColumnExpressionCore(property, querySource, selectExpression)); }
protected override Expression VisitEntityQueryable(Type elementType) { var relationalQueryCompilationContext = ((RelationalQueryCompilationContext)QueryCompilationContext); var queryMethodInfo = CreateValueReaderMethodInfo; var entityType = QueryCompilationContext.Model.GetEntityType(elementType); var selectExpression = new SelectExpression(); selectExpression .AddTable( new TableExpression( entityType.TableName(), entityType.Schema(), _querySource.ItemName.Replace("<generated>_", "t"), _querySource)); _queryModelVisitor._queriesBySource.Add(_querySource, selectExpression); var queryMethodArguments = new List <Expression> { Expression.Constant(_querySource), QueryContextParameter, QuerySourceScopeParameter, _readerParameter }; if (_queryModelVisitor.QuerySourceRequiresMaterialization(_querySource)) { foreach (var property in entityType.Properties) { selectExpression.AddToProjection(property, _querySource); } queryMethodInfo = CreateEntityMethodInfo.MakeGenericMethod(elementType); queryMethodArguments.Add(Expression.Constant(0)); } return(Expression.Call( relationalQueryCompilationContext.QueryMethodProvider.QueryMethod .MakeGenericMethod(queryMethodInfo.ReturnType), QueryContextParameter, Expression.Constant(new CommandBuilder(selectExpression, relationalQueryCompilationContext)), Expression.Lambda( Expression.Call(queryMethodInfo, queryMethodArguments), _readerParameter))); }
public override Expression?Visit(Expression?expression) { switch (expression) { case SqlExpression sqlExpression when _mappings.TryGetValue(sqlExpression, out var outer): return(outer); case ColumnExpression columnExpression when _subquery.ContainsTableReference(columnExpression): var index = _subquery.AddToProjection(columnExpression); var projectionExpression = _subquery._projection[index]; return(new ColumnExpression(projectionExpression, _tableReferenceExpression)); default: return(base.Visit(expression)); } }
private static void LiftOrderBy( SelectExpression innerJoinSelectExpression, SelectExpression targetSelectExpression, TableExpressionBase innerJoinExpression) { foreach (var ordering in innerJoinSelectExpression.OrderBy) { var orderingExpression = ordering.Expression; var aliasExpression = ordering.Expression as AliasExpression; if (aliasExpression?.Alias != null) { var columnExpression = aliasExpression.TryGetColumnExpression(); if (columnExpression != null) { orderingExpression = new ColumnExpression( aliasExpression.Alias, columnExpression.Property, columnExpression.Table); } } var index = innerJoinSelectExpression.AddToProjection(orderingExpression); var expression = innerJoinSelectExpression.Projection[index]; var newExpression = targetSelectExpression.UpdateColumnExpression(expression, innerJoinExpression); targetSelectExpression.AddToOrderBy(new Ordering(newExpression, ordering.OrderingDirection)); } if (innerJoinSelectExpression.Limit == null && innerJoinSelectExpression.Offset == null) { innerJoinSelectExpression.ClearOrderBy(); } }
private Expression BindSqlToValueBuffer(Expression sqlExpression, Type expressionType) { var targetExpression = _queryModelVisitor.QueryCompilationContext.QuerySourceMapping .GetExpression(_groupQuerySource); if (targetExpression.Type == typeof(ValueBuffer)) { var index = _selectExpression.AddToProjection(sqlExpression); var readValueExpression = _entityMaterializerSource .CreateReadValueExpression( targetExpression, expressionType, index, sqlExpression.FindProperty(expressionType)); return(Expression.Convert(readValueExpression, expressionType)); } return(null); }
Expression VisitSelectExpression(SelectExpression selectExpression) { base.Visit(selectExpression); if (!RequiresRowNumberPaging(selectExpression)) { return(selectExpression); } SelectExpression selectExpression2 = selectExpression.PushDownSubquery(); foreach (Expression item in selectExpression2.Projection) { selectExpression.AddToProjection(item.LiftExpressionFromSubquery(selectExpression2), true); } AliasExpression aliasExpression = new AliasExpression("row_number" + ((_counter != 0) ? $"{_counter}" : ""), new RowNumberExpression_DB2(selectExpression2.OrderBy)); _counter++; selectExpression2.ClearOrderBy(); selectExpression2.AddToProjection(aliasExpression, false); ColumnReferenceExpression left = new ColumnReferenceExpression(aliasExpression, selectExpression2); Expression expression = selectExpression2.Offset ?? Expression.Constant(0); if (selectExpression2.Offset != null) { selectExpression.AddToPredicate(Expression.GreaterThan(left, expression)); selectExpression2.Offset = null; } if (selectExpression2.Limit != null) { object obj = (selectExpression2.Limit as ConstantExpression)?.Value; object obj2 = (expression as ConstantExpression)?.Value; Expression right = (obj != null && obj2 != null) ? ((Expression)Expression.Constant((int)obj2 + (int)obj)) : ((Expression)Expression.Add(expression, selectExpression2.Limit)); selectExpression.AddToPredicate(Expression.LessThanOrEqual(left, right)); selectExpression2.Limit = null; } return(selectExpression); }
private IEnumerable <Expression> CreateIncludeRelatedValuesStrategyFactories( IQuerySource querySource, IEnumerable <INavigation> navigationPath) { var selectExpression = _queryCompilationContext.FindSelectExpression(querySource); var targetTableExpression = selectExpression.FindTableForQuerySource(querySource); var readerIndex = 0; foreach (var navigation in navigationPath) { if (!navigation.IsCollection()) { var targetEntityType = navigation.GetTargetType(); var targetTableName = _queryCompilationContext.GetTableName(targetEntityType); var targetTableAlias = targetTableName.First().ToString().ToLower(); var joinedTableExpression = new TableExpression( targetTableName, _queryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); var readerOffset = selectExpression.Projection.Count; var columnExpressions = targetEntityType.Properties .Select(p => new ColumnExpression( _queryCompilationContext.GetColumnName(p), p, joinedTableExpression)); var joinExpression = navigation.ForeignKey.IsRequired && navigation.PointsToPrincipal ? selectExpression .AddInnerJoin(joinedTableExpression, columnExpressions) : selectExpression .AddOuterJoin(joinedTableExpression, columnExpressions); joinExpression.Predicate = BuildJoinEqualityExpression( navigation, (navigation.PointsToPrincipal ? targetEntityType : navigation.EntityType) .GetPrimaryKey().Properties, navigation.PointsToPrincipal ? targetTableExpression : joinExpression, navigation.PointsToPrincipal ? joinExpression : targetTableExpression); targetTableExpression = joinedTableExpression; yield return (Expression.Lambda( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateReferenceIncludeRelatedValuesStrategyMethod, Expression.Convert(EntityQueryModelVisitor.QueryContextParameter, typeof(RelationalQueryContext)), Expression.Constant(readerIndex), Expression.Constant(readerOffset)))); } else { var principalTable = selectExpression.Tables.Last(t => t.QuerySource == querySource); foreach (var property in navigation.EntityType.GetPrimaryKey().Properties) { selectExpression .AddToOrderBy( _queryCompilationContext.GetColumnName(property), property, principalTable, OrderingDirection.Asc); } var targetEntityType = navigation.GetTargetType(); var targetTableName = _queryCompilationContext.GetTableName(targetEntityType); var targetTableAlias = targetTableName.First().ToString().ToLower(); var targetSelectExpression = new SelectExpression(); targetTableExpression = new TableExpression( targetTableName, _queryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); targetSelectExpression.AddTable(targetTableExpression); foreach (var property in targetEntityType.Properties) { targetSelectExpression .AddToProjection( _queryCompilationContext.GetColumnName(property), property, querySource); } var innerJoinSelectExpression = selectExpression.Clone( ((ColumnExpression)selectExpression.OrderBy.Last().Expression).TableAlias); innerJoinSelectExpression.IsDistinct = true; innerJoinSelectExpression.ClearProjection(); foreach (var columnExpression in innerJoinSelectExpression.OrderBy .Select(o => o.Expression) .Cast <ColumnExpression>()) { innerJoinSelectExpression.AddToProjection(columnExpression); } innerJoinSelectExpression.ClearOrderBy(); var primaryKeyProperties = navigation.EntityType.GetPrimaryKey().Properties; var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression); foreach (var ordering in selectExpression.OrderBy) { var columnExpression = (ColumnExpression)ordering.Expression; targetSelectExpression .AddToOrderBy( columnExpression.Name, columnExpression.Property, innerJoinExpression, ordering.OrderingDirection); } innerJoinExpression.Predicate = BuildJoinEqualityExpression( navigation, primaryKeyProperties, targetTableExpression, innerJoinExpression); var readerParameter = Expression.Parameter(typeof(DbDataReader)); selectExpression = targetSelectExpression; readerIndex++; yield return (Expression.Lambda( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateCollectionIncludeRelatedValuesStrategyMethod, Expression.Call( _queryCompilationContext.QueryMethodProvider.QueryMethod .MakeGenericMethod(typeof(IValueReader)), EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(new CommandBuilder(targetSelectExpression, _queryCompilationContext)), Expression.Lambda( Expression.Call( _createValueReaderForIncludeMethodInfo, EntityQueryModelVisitor.QueryContextParameter, readerParameter, Expression.Constant(targetEntityType)), readerParameter))))); } } }
private Expression VisitSelectExpression(SelectExpression selectExpression) { base.Visit(selectExpression); if (!RequiresRowNumberPaging(selectExpression)) { return(selectExpression); } var projections = new List <Expression>(); projections.AddRange(selectExpression.Projection); var subQuery = selectExpression.PushDownSubquery(); foreach (var projection in projections) { var alias = projection as AliasExpression; var column = projection as ColumnExpression; if (column != null) { column = new ColumnExpression(column.Name, column.Property, subQuery); selectExpression.AddToProjection(column); continue; } column = alias?.TryGetColumnExpression(); if (column != null) { column = new ColumnExpression(column.Name, column.Property, subQuery); alias = new AliasExpression(alias.Alias, column); selectExpression.AddToProjection(alias); } else { selectExpression.AddToProjection(projection); } } if (subQuery.OrderBy.Count == 0) { subQuery.AddToOrderBy( new Ordering(new SqlFunctionExpression("@@RowCount", typeof(int)), OrderingDirection.Asc)); } var columnExpression = new ColumnExpression(RowNumberColumnName, typeof(int), subQuery); var rowNumber = new RowNumberExpression(columnExpression, subQuery.OrderBy); subQuery.ClearOrderBy(); subQuery.ClearProjection(); subQuery.AddToProjection(rowNumber); subQuery.IsProjectStar = true; Expression predicate = null; var offset = subQuery.Offset ?? 0; if (subQuery.Offset.HasValue) { predicate = Expression.GreaterThan(columnExpression, Expression.Constant(offset)); } if (subQuery.Limit.HasValue) { var exp = Expression.LessThanOrEqual(columnExpression, Expression.Constant(offset + subQuery.Limit.Value)); if (predicate != null) { exp = Expression.AndAlso(predicate, exp); } predicate = exp; } selectExpression.Predicate = predicate; return(selectExpression); }
public override Expression Visit(Expression expression) { if (expression == null) { return(null); } if (!(expression is NewExpression || expression is MemberInitExpression || expression is EntityShaperExpression || expression is IncludeExpression)) { // This skips the group parameter from GroupJoin if (expression is ParameterExpression parameter && parameter.Type.IsGenericType && parameter.Type.GetGenericTypeDefinition() == typeof(IEnumerable <>)) { return(parameter); } if (_clientEval) { if (expression is ConstantExpression) { return(expression); } if (expression is ParameterExpression parameterExpression) { return(Expression.Call( _getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type), QueryCompilationContext.QueryContextParameter, Expression.Constant(parameterExpression.Name))); } if (expression is MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression) { return(_selectExpression.AddCollectionProjection( _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( materializeCollectionNavigationExpression.Subquery), materializeCollectionNavigationExpression.Navigation, null)); } if (expression is MethodCallExpression methodCallExpression) { if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.DeclaringType == typeof(Enumerable) && methodCallExpression.Method.Name == nameof(Enumerable.ToList)) { var elementType = methodCallExpression.Method.GetGenericArguments()[0]; var result = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression.Arguments[0]); return(_selectExpression.AddCollectionProjection(result, null, elementType)); } var subquery = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression); if (subquery != null) { if (subquery.ResultType == ResultType.Enumerable) { return(_selectExpression.AddCollectionProjection(subquery, null, subquery.ShaperExpression.Type)); } } } var translation = _sqlTranslator.Translate(expression); if (translation == null) { return(base.Visit(expression)); } else { return(new ProjectionBindingExpression(_selectExpression, _selectExpression.AddToProjection(translation), expression.Type)); } } else { var translation = _sqlTranslator.Translate(expression); if (translation == null) { return(null); } _projectionMapping[_projectionMembers.Peek()] = translation; return(new ProjectionBindingExpression(_selectExpression, _projectionMembers.Peek(), expression.Type)); } } return(base.Visit(expression)); }
public override Expression?Visit(Expression?expression) { if (expression == null) { return(null); } if (!(expression is NewExpression || expression is MemberInitExpression || expression is EntityShaperExpression || expression is IncludeExpression)) { // This skips the group parameter from GroupJoin if (expression is ParameterExpression parameter && parameter.Type.IsGenericType && parameter.Type.GetGenericTypeDefinition() == typeof(IEnumerable <>)) { return(parameter); } if (_clientEval) { switch (expression) { case ConstantExpression _: return(expression); case ProjectionBindingExpression projectionBindingExpression: if (projectionBindingExpression.Index is int index) { var newIndex = _selectExpression.AddToProjection(_existingProjections[index]); return(new ProjectionBindingExpression(_selectExpression, newIndex, expression.Type)); } if (projectionBindingExpression.ProjectionMember != null) { // This would be SqlExpression. EntityProjectionExpression would be wrapped inside EntityShaperExpression. var mappedProjection = (SqlExpression)((SelectExpression)projectionBindingExpression.QueryExpression) .GetMappedProjection(projectionBindingExpression.ProjectionMember); return(new ProjectionBindingExpression( _selectExpression, _selectExpression.AddToProjection(mappedProjection), expression.Type)); } throw new InvalidOperationException(CoreStrings.TranslationFailed(projectionBindingExpression.Print())); case ParameterExpression parameterExpression: if (parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) == true) { return(Expression.Call( _getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type), QueryCompilationContext.QueryContextParameter, Expression.Constant(parameterExpression.Name))); } throw new InvalidOperationException(CoreStrings.TranslationFailed(parameterExpression.Print())); case MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression: return(_selectExpression.AddCollectionProjection( _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( materializeCollectionNavigationExpression.Subquery) !, materializeCollectionNavigationExpression.Navigation, materializeCollectionNavigationExpression.Navigation.ClrType.TryGetSequenceType() !)); case MethodCallExpression methodCallExpression: { if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.DeclaringType == typeof(Enumerable) && methodCallExpression.Method.Name == nameof(Enumerable.ToList)) { var elementType = methodCallExpression.Method.GetGenericArguments()[0]; var result = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( methodCallExpression.Arguments[0]); if (result != null) { return(_selectExpression.AddCollectionProjection(result, null, elementType)); } } else { var subquery = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression); if (subquery != null) { if (subquery.ResultCardinality == ResultCardinality.Enumerable) { return(_selectExpression.AddCollectionProjection(subquery, null, subquery.ShaperExpression.Type)); }
private Expression VisitSelectExpression(SelectExpression selectExpression) { base.Visit(selectExpression); if (!RequiresRowNumberPaging(selectExpression)) { return(selectExpression); } var subQuery = selectExpression.PushDownSubquery(); foreach (var projection in subQuery.Projection) { var alias = projection as AliasExpression; var column = projection as ColumnExpression; if (column != null) { column = new ColumnExpression(column.Name, column.Property, subQuery); selectExpression.AddToProjection(column); continue; } column = alias?.TryGetColumnExpression(); if (column != null) { column = new ColumnExpression(column.Name, column.Property, subQuery); alias = new AliasExpression(alias.Alias, column); selectExpression.AddToProjection(alias); } else { column = new ColumnExpression(alias.Alias, alias.Expression.Type, subQuery); selectExpression.AddToProjection(column); } } if (subQuery.OrderBy.Count == 0) { subQuery.AddToOrderBy( new Ordering(new SqlFunctionExpression("@@RowCount", typeof(int)), OrderingDirection.Asc)); } var columnExpression = new ColumnExpression(RowNumberColumnName, typeof(int), subQuery); var rowNumber = new RowNumberExpression(columnExpression, subQuery.OrderBy); subQuery.ClearOrderBy(); subQuery.AddToProjection(rowNumber, false); Expression predicate = null; var offset = subQuery.Offset ?? Expression.Constant(0); if (subQuery.Offset != null) { predicate = Expression.GreaterThan(columnExpression, offset); } if (subQuery.Limit != null) { var constantValue = (subQuery.Limit as ConstantExpression)?.Value; var offsetValue = (offset as ConstantExpression)?.Value; var limitExpression = constantValue != null && offsetValue != null ? (Expression)Expression.Constant((int)offsetValue + (int)constantValue) : Expression.Add(offset, subQuery.Limit); var expression = Expression.LessThanOrEqual(columnExpression, limitExpression); if (predicate != null) { expression = Expression.AndAlso(predicate, expression); } predicate = expression; } selectExpression.Predicate = predicate; return(selectExpression); }
public override Expression Visit(Expression expression) { if (expression == null) { return(null); } if (!(expression is NewExpression || expression is MemberInitExpression || expression is EntityShaperExpression || expression is IncludeExpression)) { // This skips the group parameter from GroupJoin if (expression is ParameterExpression parameter && parameter.Type.IsGenericType && parameter.Type.GetGenericTypeDefinition() == typeof(IEnumerable <>)) { return(parameter); } if (_clientEval) { if (expression is ConstantExpression) { return(expression); } if (expression is ParameterExpression parameterExpression) { return(Expression.Call( _getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type), QueryCompilationContext.QueryContextParameter, Expression.Constant(parameterExpression.Name))); } if (expression is MethodCallExpression methodCallExpression && methodCallExpression.Method.Name == "MaterializeCollectionNavigation") { var result = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression.Arguments[0]); var navigation = (INavigation)((ConstantExpression)methodCallExpression.Arguments[1]).Value; return(_selectExpression.AddCollectionProjection(result, navigation)); } var translation = _sqlTranslator.Translate(expression); if (translation == null) { return(base.Visit(expression)); } else { return(_selectExpression.AddToProjection(translation, expression.Type)); } } else { var translation = _sqlTranslator.Translate(expression); if (translation == null) { return(null); } _projectionMapping[_projectionMembers.Peek()] = translation; return(new ProjectionBindingExpression(_selectExpression, _projectionMembers.Peek(), expression.Type)); } } return(base.Visit(expression)); }
private void IncludeCollection(IQuerySource querySource, Type resultType, Expression accessorLambda, INavigation navigation) { var selectExpression = QueryCompilationContext.FindSelectExpression(querySource); var primaryKeyProperties = navigation.EntityType.GetPrimaryKey().Properties; foreach (var property in primaryKeyProperties) { selectExpression .AddToOrderBy( QueryCompilationContext.GetColumnName(property), property, querySource, OrderingDirection.Asc); } var targetEntityType = navigation.GetTargetType(); var targetTableName = QueryCompilationContext.GetTableName(targetEntityType); var targetSelectExpression = new SelectExpression(); var targetTableAlias = CreateUniqueAlias(selectExpression, targetTableName.First().ToString().ToLower()); var targetTableExpression = new TableExpression( targetTableName, QueryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); targetSelectExpression.AddTable(targetTableExpression); foreach (var property in targetEntityType.Properties) { targetSelectExpression .AddToProjection( QueryCompilationContext.GetColumnName(property), property, querySource); } var innerJoinSelectExpression = selectExpression.Clone( ((ColumnExpression)selectExpression.OrderBy.First().Expression).TableAlias); innerJoinSelectExpression.IsDistinct = true; innerJoinSelectExpression.ClearProjection(); foreach (var columnExpression in innerJoinSelectExpression.OrderBy .Select(o => o.Expression) .Cast <ColumnExpression>()) { innerJoinSelectExpression.AddToProjection(columnExpression); } innerJoinSelectExpression.ClearOrderBy(); var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression); targetSelectExpression.AddToOrderBy(selectExpression.OrderBy); innerJoinExpression.Predicate = BuildJoinEqualityExpression(navigation, primaryKeyProperties, targetTableExpression, innerJoinExpression); var readerParameter = Expression.Parameter(typeof(DbDataReader)); Expression = Expression.Call( QueryCompilationContext.QueryMethodProvider.IncludeCollectionMethod .MakeGenericMethod(resultType), QueryContextParameter, Expression, Expression.Constant(navigation), Expression.Call( QueryCompilationContext.QueryMethodProvider.QueryMethod .MakeGenericMethod(typeof(IValueReader)), QueryContextParameter, Expression.Constant(new CommandBuilder(targetSelectExpression, QueryCompilationContext)), Expression.Lambda( Expression.Call( _createValueReaderForIncludeMethodInfo, QueryContextParameter, readerParameter, Expression.Constant(targetEntityType)), readerParameter)), accessorLambda); }