protected static void ApplyIncludeExpressionsToQueryModel( QueryModel queryModel, QuerySourceReferenceExpression querySourceReferenceExpression, Expression expression) { var includeReplacingExpressionVisitor = new IncludeReplacingExpressionVisitor(); foreach (var groupResultOperator in queryModel.ResultOperators.OfType <GroupResultOperator>()) { var newElementSelector = includeReplacingExpressionVisitor.Replace( querySourceReferenceExpression, expression, groupResultOperator.ElementSelector); if (!ReferenceEquals(newElementSelector, groupResultOperator.ElementSelector)) { groupResultOperator.ElementSelector = newElementSelector; return; } } queryModel.SelectClause.TransformExpressions( e => includeReplacingExpressionVisitor.Replace( querySourceReferenceExpression, expression, e)); }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public virtual void CompileIncludes( [NotNull] QueryModel queryModel, [NotNull] ICollection <IncludeResultOperator> includeResultOperators, bool trackingQuery) { var includeGroupings = CreateIncludeSpecifications(queryModel, includeResultOperators) .GroupBy(a => a.QuerySourceReferenceExpression); foreach (var includeGrouping in includeGroupings) { var entityParameter = Expression.Parameter(includeGrouping.Key.Type, name: "entity"); var propertyExpressions = new List <Expression>(); var blockExpressions = new List <Expression>(); if (trackingQuery) { blockExpressions.Add( Expression.Call( _queryBufferParameter, _startTrackingMethodInfo, entityParameter, Expression.Constant( _queryCompilationContext.Model .FindEntityType(entityParameter.Type)))); } var includedIndex = 0; foreach (var includeSpecification in includeGrouping) { _queryCompilationContext.Logger .LogDebug( CoreEventId.IncludingNavigation, () => CoreStrings.LogIncludingNavigation(includeSpecification.IncludeResultOperator)); propertyExpressions.AddRange( includeSpecification.NavigationPath .Select((t, i) => includeSpecification.NavigationPath .Take(i + 1) .Aggregate( (Expression)includeSpecification.QuerySourceReferenceExpression, EntityQueryModelVisitor.CreatePropertyExpression))); blockExpressions.Add( BuildIncludeExpressions( includeSpecification.NavigationPath, entityParameter, trackingQuery, ref includedIndex, navigationIndex: 0)); // TODO: Hack until new Include fully implemented includeResultOperators.Remove(includeSpecification.IncludeResultOperator); } var includeReplacingExpressionVisitor = new IncludeReplacingExpressionVisitor( includeGrouping.Key, Expression.Call( IncludeMethodInfo.MakeGenericMethod(includeGrouping.Key.Type), includeGrouping.Key, Expression.NewArrayInit( typeof(object), propertyExpressions), trackingQuery ? (Expression) Expression.Property( Expression.Property( EntityQueryModelVisitor.QueryContextParameter, propertyName: "StateManager"), propertyName: "Value") : Expression.Default(typeof(IStateManager)), trackingQuery ? (Expression) Expression.Property( EntityQueryModelVisitor.QueryContextParameter, propertyName: "QueryBuffer") : Expression.Default(typeof(IQueryBuffer)), Expression.Lambda( Expression.Block(typeof(void), blockExpressions), entityParameter, _includedParameter, _stateManagerParameter, _queryBufferParameter))); queryModel.SelectClause.TransformExpressions(includeReplacingExpressionVisitor.Visit); } }