public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index) { Check.NotNull(fromClause, nameof(fromClause)); Check.NotNull(queryModel, nameof(queryModel)); base.VisitAdditionalFromClause(fromClause, queryModel, index); RequiresClientSelectMany = true; var selectExpression = TryGetQuery(fromClause); if (selectExpression != null && selectExpression.Tables.Count == 1) { var previousQuerySource = FindPreviousQuerySource(queryModel, index); if (previousQuerySource != null) { var previousSelectExpression = TryGetQuery(previousQuerySource); if (previousSelectExpression != null) { var readerOffset = previousSelectExpression.Projection.Count; var correlated = selectExpression.IsCorrelated(); if (correlated) { if (!QueryCompilationContext.IsCrossApplySupported) { return; } previousSelectExpression .AddCrossApply(selectExpression.Tables.First(), selectExpression.Projection); } else { previousSelectExpression .AddCrossJoin(selectExpression.Tables.First(), selectExpression.Projection); } _queriesBySource.Remove(fromClause); Expression = new QueryFlatteningExpressionVisitor( previousQuerySource, fromClause, QueryCompilationContext, readerOffset, LinqOperatorProvider.SelectMany) .Visit(Expression); RequiresClientSelectMany = false; } } } }
public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index) { Check.NotNull(fromClause, nameof(fromClause)); Check.NotNull(queryModel, nameof(queryModel)); base.VisitAdditionalFromClause(fromClause, queryModel, index); RequiresClientSelectMany = true; var selectExpression = TryGetQuery(fromClause); if (selectExpression != null) { var previousQuerySource = FindPreviousQuerySource(queryModel, index); if (previousQuerySource != null) { var previousSelectExpression = TryGetQuery(previousQuerySource); if (previousSelectExpression != null) { var readerOffset = previousSelectExpression.Projection.Count; previousSelectExpression .AddCrossJoin(selectExpression.Tables.Single(), selectExpression.Projection); _queriesBySource.Remove(fromClause); Expression = new QueryFlatteningExpressionVisitor( previousQuerySource, fromClause, QueryCompilationContext, readerOffset, LinqOperatorProvider.SelectMany) .Visit(Expression); RequiresClientSelectMany = false; } } } }
public override void VisitJoinClause(JoinClause joinClause, QueryModel queryModel, int index) { Check.NotNull(joinClause, nameof(joinClause)); Check.NotNull(queryModel, nameof(queryModel)); var previousQuerySource = FindPreviousQuerySource(queryModel, index); var previousSelectExpression = previousQuerySource != null ? TryGetQuery(previousQuerySource) : null; var previousSelectProjectionCount = previousSelectExpression?.Projection.Count ?? -1; base.VisitJoinClause(joinClause, queryModel, index); if (previousSelectExpression != null) { var selectExpression = TryGetQuery(joinClause); if (selectExpression != null) { var filteringExpressionVisitor = new SqlTranslatingExpressionVisitor(this, targetSelectExpression: null); var predicate = filteringExpressionVisitor .Visit( Expression.Equal( joinClause.OuterKeySelector, joinClause.InnerKeySelector)); if (predicate != null) { _queriesBySource.Remove(joinClause); previousSelectExpression.RemoveRangeFromProjection(previousSelectProjectionCount); var innerJoinExpression = previousSelectExpression .AddInnerJoin( selectExpression.Tables.Single(), QueryCompilationContext .QuerySourceRequiresMaterialization(joinClause) ? selectExpression.Projection : Enumerable.Empty <Expression>()); innerJoinExpression.Predicate = predicate; Expression = new QueryFlatteningExpressionVisitor( previousQuerySource, joinClause, QueryCompilationContext, previousSelectProjectionCount, LinqOperatorProvider.Join) .Visit(Expression); } else { previousSelectExpression.RemoveRangeFromProjection(previousSelectProjectionCount); } } } }
protected virtual void OptimizeJoinClause( [NotNull] JoinClause joinClause, [NotNull] QueryModel queryModel, int index, [NotNull] Action baseVisitAction, [NotNull] MethodInfo operatorToFlatten, bool outerJoin = false) { Check.NotNull(joinClause, nameof(joinClause)); Check.NotNull(queryModel, nameof(queryModel)); Check.NotNull(baseVisitAction, nameof(baseVisitAction)); Check.NotNull(operatorToFlatten, nameof(operatorToFlatten)); var previousQuerySource = FindPreviousQuerySource(queryModel, index); var previousSelectExpression = previousQuerySource != null ? TryGetQuery(previousQuerySource) : null; var previousSelectProjectionCount = previousSelectExpression?.Projection.Count ?? -1; baseVisitAction(); if (previousSelectExpression != null) { var selectExpression = TryGetQuery(joinClause); if (selectExpression != null) { var sqlTranslatingExpressionVisitor = new SqlTranslatingExpressionVisitor(this); var predicate = sqlTranslatingExpressionVisitor .Visit( Expression.Equal( joinClause.OuterKeySelector, joinClause.InnerKeySelector)); if (predicate != null) { _queriesBySource.Remove(joinClause); previousSelectExpression.RemoveRangeFromProjection(previousSelectProjectionCount); var tableExpression = selectExpression.Tables.Single(); var projection = QueryCompilationContext .QuerySourceRequiresMaterialization(joinClause) ? selectExpression.Projection : Enumerable.Empty <Expression>(); var joinExpression = !outerJoin ? previousSelectExpression.AddInnerJoin(tableExpression, projection) : previousSelectExpression.AddOuterJoin(tableExpression, projection); joinExpression.Predicate = predicate; Expression = new QueryFlatteningExpressionVisitor( previousQuerySource, joinClause, QueryCompilationContext, previousSelectProjectionCount, operatorToFlatten) .Visit(Expression); } else { previousSelectExpression .RemoveRangeFromProjection(previousSelectProjectionCount); } } } }