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(); } }
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 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); }
private IEnumerable <Expression> CreateIncludeRelatedValuesStrategyFactories( IQuerySource querySource, IEnumerable <INavigation> navigationPath) { var selectExpression = _queryCompilationContext.FindSelectExpression(querySource); var targetTableExpression = selectExpression.FindTableForQuerySource(querySource); var readerIndex = 0; var canProduceInnerJoin = true; foreach (var navigation in navigationPath) { var targetEntityType = navigation.GetTargetType(); var targetTableName = _queryCompilationContext.GetTableName(targetEntityType); var targetTableAlias = targetTableName.First().ToString().ToLower(); if (!navigation.IsCollection()) { var joinedTableExpression = new TableExpression( targetTableName, _queryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); var readerOffset = selectExpression.Projection.Count; canProduceInnerJoin = canProduceInnerJoin && (navigation.ForeignKey.IsRequired && navigation.PointsToPrincipal); var joinExpression = canProduceInnerJoin ? selectExpression .AddInnerJoin(joinedTableExpression) : selectExpression .AddOuterJoin(joinedTableExpression); var materializer = new MaterializerFactory( _queryCompilationContext.EntityMaterializerSource) .CreateMaterializer( targetEntityType, selectExpression, projectionAdder: (p, se) => se.AddToProjection( new ColumnExpression( _queryCompilationContext.GetColumnName(p), p, joinedTableExpression)) - readerOffset, querySource: null); 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), materializer))); } 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 targetSelectExpression = new SelectExpression(); targetTableExpression = new TableExpression( targetTableName, _queryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); targetSelectExpression.AddTable(targetTableExpression); var materializer = new MaterializerFactory( _queryCompilationContext.EntityMaterializerSource) .CreateMaterializer( targetEntityType, targetSelectExpression, (p, se) => se.AddToProjection( _queryCompilationContext.GetColumnName(p), p, querySource), querySource: null); 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.Alias ?? 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)), materializer))); } } }