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));
            }
Ejemplo n.º 2
0
        /// <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);
            }
        }