public override void VisitMainFromClause( [NotNull] MainFromClause fromClause, [NotNull] QueryModel queryModel) { Check.NotNull(fromClause, nameof(fromClause)); Check.NotNull(queryModel, nameof(queryModel)); _expression = CompileMainFromClauseExpression(fromClause, queryModel); var sequenceType = _expression.Type.GetSequenceType(); var elementScoped = sequenceType.IsConstructedGenericType && sequenceType.GetGenericTypeDefinition() == typeof(QueryResultScope <>); Type elementType; if (elementScoped) { elementType = sequenceType.GetTypeInfo().GenericTypeArguments[0]; } else { elementType = sequenceType; _expression = CreateScope(_expression, elementType, fromClause); } _expression = Expression.Call( LinqOperatorProvider.SelectMany .MakeGenericMethod(typeof(QueryResultScope), typeof(QueryResultScope)), Expression.Call( LinqOperatorProvider.ToSequence .MakeGenericMethod(typeof(QueryResultScope)), QueryResultScopeParameter), Expression.Lambda(_expression, QueryResultScopeParameter)); if (!_queryCompilationContext.QuerySourceMapping.ContainsMapping(fromClause)) { _queryCompilationContext.QuerySourceMapping.AddMapping( fromClause, QueryResultScope.GetResult(QueryResultScopeParameter, fromClause, elementType)); } }
public virtual object GetResult([NotNull] IQuerySource querySource) => _querySource == querySource ? UntypedResult : _parentScope.GetResult(querySource);
private Expression LiftSubQuery( IQuerySource querySource, Expression itemsExpression, QueryModel queryModel, Expression expression) { SelectExpression subSelectExpression; if (_subqueriesBySource.TryGetValue(querySource, out subSelectExpression) && (!subSelectExpression.OrderBy.Any() || subSelectExpression.Limit != null)) { subSelectExpression.PushDownSubquery().QuerySource = querySource; AddQuery(querySource, subSelectExpression); _subqueriesBySource.Remove(querySource); var shapedQueryMethodExpression = new ShapedQueryFindingExpressionVisitor(QueryCompilationContext) .Find(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) { var subQueryModel = (itemsExpression as SubQueryExpression)?.QueryModel; if (subQueryModel != null) { queryModel.SelectClause.Selector = subQueryModel.SelectClause.Selector; QueryCompilationContext.QuerySourceMapping .ReplaceMapping( subQueryModel.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); }
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); }
public override void VisitGroupJoinClause( [NotNull] GroupJoinClause groupJoinClause, [NotNull] QueryModel queryModel, int index) { Check.NotNull(groupJoinClause, nameof(groupJoinClause)); Check.NotNull(queryModel, nameof(queryModel)); var outerKeySelector = ReplaceClauseReferences(groupJoinClause.JoinClause.OuterKeySelector, groupJoinClause); var innerExpression = CompileGroupJoinInnerSequenceExpression(groupJoinClause, queryModel); var innerSequenceType = innerExpression.Type.GetSequenceType(); var innerItemParameter = Expression.Parameter(innerSequenceType); var innerElementScoped = innerSequenceType.IsConstructedGenericType && innerSequenceType.GetGenericTypeDefinition() == typeof(QueryResultScope <>); Type innerElementType; var querySourceMapping = _queryCompilationContext.QuerySourceMapping; if (innerElementScoped) { innerElementType = innerSequenceType.GetTypeInfo().GenericTypeArguments[0]; querySourceMapping.AddMapping( groupJoinClause.JoinClause, QueryResultScope.GetResult(innerItemParameter, groupJoinClause.JoinClause, innerElementType)); } else { innerElementType = innerSequenceType; querySourceMapping.AddMapping(groupJoinClause.JoinClause, innerItemParameter); } var innerKeySelector = ReplaceClauseReferences(groupJoinClause.JoinClause.InnerKeySelector, groupJoinClause); var innerItemsParameter = Expression.Parameter(innerExpression.Type); _expression = Expression.Call( LinqOperatorProvider.GroupJoin.MakeGenericMethod( typeof(QueryResultScope), innerSequenceType, outerKeySelector.Type, typeof(QueryResultScope)), _expression, innerExpression, Expression.Lambda(outerKeySelector, QueryResultScopeParameter), Expression.Lambda(innerKeySelector, innerItemParameter), Expression.Lambda( QueryResultScope .Create( groupJoinClause, innerElementScoped ? Expression.Call( LinqOperatorProvider.Select .MakeGenericMethod( innerSequenceType, innerElementType), innerItemsParameter, Expression.Lambda( QueryResultScope.GetResult( innerItemParameter, groupJoinClause.JoinClause, innerElementType), innerItemParameter)) : (Expression)innerItemsParameter, QueryResultScopeParameter), QueryResultScopeParameter, innerItemsParameter)); var expressionTypeInfo = _expression.Type.GetTypeInfo(); querySourceMapping.AddMapping( groupJoinClause, QueryResultScope .GetResult( QueryResultScopeParameter, groupJoinClause, expressionTypeInfo.GetGenericTypeDefinition() .MakeGenericType(innerElementType))); }