private Expression LiftSubQuery( IQuerySource querySource, Expression itemsExpression, Expression expression) { var subQueryExpression = itemsExpression as SubQueryExpression; if (subQueryExpression == null) { return(expression); } var subQueryModelVisitor = (RelationalQueryModelVisitor)QueryCompilationContext .CreateQueryModelVisitor(this); subQueryModelVisitor.VisitSubQueryModel(subQueryExpression.QueryModel); if ((subQueryModelVisitor.Queries.Count == 1) && !subQueryModelVisitor.RequiresClientEval && !subQueryModelVisitor.RequiresClientSelectMany && !subQueryModelVisitor.RequiresClientJoin && !subQueryModelVisitor.RequiresClientFilter && !subQueryModelVisitor.RequiresClientProjection && !subQueryModelVisitor.RequiresClientOrderBy && !subQueryModelVisitor.RequiresClientResultOperator) { var subSelectExpression = subQueryModelVisitor.Queries.First(); if ((!subSelectExpression.OrderBy.Any() || (subSelectExpression.Limit != null)) && (QueryCompilationContext.IsLateralJoinSupported || !subSelectExpression.IsCorrelated() || !(querySource is AdditionalFromClause))) { subSelectExpression.PushDownSubquery().QuerySource = querySource; AddQuery(querySource, subSelectExpression); var liftSubQuery = new QuerySourceUpdater( querySource, QueryCompilationContext, LinqOperatorProvider, subSelectExpression) .Visit(subQueryModelVisitor.Expression); return (liftSubQuery); } } return(expression); }
protected override Expression VisitSubQueryExpression(SubQueryExpression expression) { var queryModelVisitor = QueryCompilationContext.CreateQueryModelVisitor(); queryModelVisitor.VisitQueryModel(expression.QueryModel); var subExpression = queryModelVisitor.Expression; if (queryModelVisitor._streamedSequenceInfo == null) { return(subExpression); } if (typeof(IQueryable).GetTypeInfo().IsAssignableFrom(expression.Type.GetTypeInfo())) { subExpression = Expression.Call( _asQueryableShim.MakeGenericMethod( queryModelVisitor._streamedSequenceInfo.ResultItemType), subExpression); } return(Expression.Convert(subExpression, expression.Type)); }
private Expression LiftSubQuery( IQuerySource querySource, Expression itemsExpression, QueryModel queryModel, Expression expression) { var subQueryExpression = itemsExpression as SubQueryExpression; if (subQueryExpression == null) { return(expression); } var subQueryModelVisitor = (RelationalQueryModelVisitor)QueryCompilationContext.CreateQueryModelVisitor(this); subQueryModelVisitor.VisitSubQueryModel(subQueryExpression.QueryModel); SelectExpression subSelectExpression = null; if (subQueryModelVisitor.Queries.Count == 1 && !subQueryModelVisitor.RequiresClientFilter && !subQueryModelVisitor.RequiresClientSelectMany && !subQueryModelVisitor.RequiresClientProjection && !subQueryModelVisitor.RequiresClientResultOperator) { subSelectExpression = subQueryModelVisitor.Queries.First(); } if (subSelectExpression != null && (!subSelectExpression.OrderBy.Any() || subSelectExpression.Limit != null) && (QueryCompilationContext.IsCrossApplySupported || (!subSelectExpression.IsCorrelated() || !(querySource is AdditionalFromClause)))) { subSelectExpression.PushDownSubquery().QuerySource = querySource; AddQuery(querySource, subSelectExpression); var shapedQueryMethodExpression = new ShapedQueryFindingExpressionVisitor(QueryCompilationContext) .Find(subQueryModelVisitor.Expression); var shaperLambda = (LambdaExpression)shapedQueryMethodExpression.Arguments[2]; var shaperMethodCall = (MethodCallExpression)shaperLambda.Body; var shaperMethod = shaperMethodCall.Method; var shaperMethodArgs = shaperMethodCall.Arguments.ToList(); if (!QueryCompilationContext.QuerySourceRequiresMaterialization(querySource) && shaperMethod.MethodIsClosedFormOf(RelationalEntityQueryableExpressionVisitor.CreateEntityMethodInfo)) { shaperMethod = RelationalEntityQueryableExpressionVisitor.CreateValueBufferMethodInfo; shaperMethodArgs.RemoveRange(5, 5); } else { subSelectExpression.ExplodeStarProjection(); } var innerQuerySource = (IQuerySource)((ConstantExpression)shaperMethodArgs[0]).Value; foreach (var queryAnnotation in QueryCompilationContext.QueryAnnotations .Where(qa => qa.QuerySource == innerQuerySource)) { queryAnnotation.QuerySource = querySource; } shaperMethodArgs[0] = Expression.Constant(querySource); var querySourceReferenceExpression = queryModel.SelectClause.Selector as QuerySourceReferenceExpression; if (querySourceReferenceExpression != null && querySourceReferenceExpression.ReferencedQuerySource == querySource) { if (subQueryExpression.QueryModel != null) { queryModel.SelectClause.Selector = subQueryExpression.QueryModel.SelectClause.Selector; QueryCompilationContext.QuerySourceMapping .ReplaceMapping( subQueryExpression.QueryModel.MainFromClause, QueryResultScope.GetResult( QueryResultScopeParameter, querySource, shaperMethod.ReturnType.GenericTypeArguments[0])); } } return(Expression.Call( QueryCompilationContext.QueryMethodProvider.ShapedQueryMethod .MakeGenericMethod(shaperMethod.ReturnType), shapedQueryMethodExpression.Arguments[0], shapedQueryMethodExpression.Arguments[1], Expression.Lambda( Expression.Call(shaperMethod, shaperMethodArgs), shaperLambda.Parameters[0]))); } return(expression); }