public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index) { base.VisitAdditionalFromClause(fromClause, queryModel, index); var selectExpression = TryGetQuery(fromClause); if (selectExpression != null) { var previousQuerySource = index == 0 ? queryModel.MainFromClause : queryModel.BodyClauses[index - 1] as IQuerySource; 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 QueryFlatteningExpressionTreeVisitor( previousQuerySource, fromClause, QueryCompilationContext, readerOffset, LinqOperatorProvider.SelectMany) .VisitExpression(Expression); } } } }
public override void VisitJoinClause(JoinClause joinClause, QueryModel queryModel, int index) { var previousQuerySource = index == 0 ? queryModel.MainFromClause : queryModel.BodyClauses[index - 1] as IQuerySource; 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 filteringExpressionTreeVisitor = new SqlTranslatingExpressionTreeVisitor(this); var predicate = filteringExpressionTreeVisitor .VisitExpression( Expression.Equal( joinClause.OuterKeySelector, joinClause.InnerKeySelector)); if (predicate != null) { _queriesBySource.Remove(joinClause); previousSelectExpression.RemoveRangeFromProjection(previousSelectProjectionCount); var innerJoinExpression = previousSelectExpression .AddInnerJoin( selectExpression.Tables.Single(), QuerySourceRequiresMaterialization(joinClause) ? selectExpression.Projection : Enumerable.Empty <Expression>()); innerJoinExpression.Predicate = predicate; Expression = new QueryFlatteningExpressionTreeVisitor( previousQuerySource, joinClause, QueryCompilationContext, previousSelectProjectionCount, LinqOperatorProvider.Join) .VisitExpression(Expression); } else { previousSelectExpression.RemoveRangeFromProjection(previousSelectProjectionCount); } } } }