示例#1
0
        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);
        }
示例#2
0
            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));
            }
示例#3
0
        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);
        }