예제 #1
0
        public override Expression Apply(Expression expression, Random random)
        {
            var i    = random.Next(_expressionFinder.FoundExpressions.Count);
            var expr = _expressionFinder.FoundExpressions[i];

            var entityType  = expr.Type.GetGenericArguments()[0];
            var navigations = Context.Model.FindEntityType(entityType)?.GetNavigations().ToList();

            var prm = Expression.Parameter(entityType, "prm");

            if (navigations != null && navigations.Any())
            {
                var j          = random.Next(navigations.Count);
                var navigation = navigations[j];

                var includeMethod = IncludeMethodInfo.MakeGenericMethod(entityType, navigation.ClrType);

                var injector = new ExpressionInjector(
                    _expressionFinder.FoundExpressions[i],
                    e => Expression.Call(
                        includeMethod,
                        e,
                        Expression.Lambda(Expression.Property(prm, navigation.Name), prm)));

                return(injector.Visit(expression));
            }

            return(expression);
        }
예제 #2
0
        public override Expression Apply(Expression expression, Random random)
        {
            var i           = random.Next(_expressionFinder.FoundExpressions.Count);
            var expr        = _expressionFinder.FoundExpressions[i];
            var thenInclude = random.Next(3) > 0;

            var entityType          = expr.Type.GetGenericArguments()[0];
            var propertyType        = expr.Type.GetGenericArguments()[1];
            var propertyElementType = IsEnumerableType(propertyType) || propertyType.GetInterfaces().Any(ii => IsEnumerableType(ii))
                ? propertyType.GetGenericArguments()[0]
                : propertyType;

            var navigations = thenInclude
                ? Context.Model.FindEntityType(propertyElementType)?.GetNavigations().ToList()
                : Context.Model.FindEntityType(entityType)?.GetNavigations().ToList();

            var prm = thenInclude
                ? Expression.Parameter(propertyElementType, "prm")
                : Expression.Parameter(entityType, "prm");

            if (navigations != null &&
                navigations.Any())
            {
                var j          = random.Next(navigations.Count);
                var navigation = navigations[j];

                if (thenInclude)
                {
                    var thenIncludeMethod = IsEnumerableType(propertyType) || propertyType.GetInterfaces().Any(ii => IsEnumerableType(ii))
                        ? ThenIncludeCollectionMethodInfo.MakeGenericMethod(entityType, propertyElementType, navigation.ClrType)
                        : ThenIncludeReferenceMethodInfo.MakeGenericMethod(entityType, propertyElementType, navigation.ClrType);

                    var injector = new ExpressionInjector(
                        _expressionFinder.FoundExpressions[i],
                        e => Expression.Call(
                            thenIncludeMethod,
                            e,
                            Expression.Lambda(Expression.Property(prm, navigation.Name), prm)));

                    return(injector.Visit(expression));
                }
                else
                {
                    var includeMethod = IncludeMethodInfo.MakeGenericMethod(entityType, navigation.ClrType);

                    var injector = new ExpressionInjector(
                        _expressionFinder.FoundExpressions[i],
                        e => Expression.Call(
                            includeMethod,
                            e,
                            Expression.Lambda(Expression.Property(prm, navigation.Name), prm)));

                    return(injector.Visit(expression));
                }
            }

            return(expression);
        }
예제 #3
0
        // to get this to work, code was referenced and borrowed from https://github.com/aspnet/EntityFramework/blob/dev/src/EntityFramework.Core/EntityFrameworkQueryableExtensions.cs
        public static IQueryable <T> IncludeString <T>(this IQueryable <T> query, string include) where T : class, new()
        {
            // need to get the first include, and then append the thenincludes
            Type                             childType, parentType = typeof(T);
            MethodInfo                       includeMethodInfo;
            MethodInfo                       thenIncludeMethodInfo;
            MethodCallExpression             methodCallExpression;
            IIncludableQueryable <T, object> resultQuery;

            string[] includeProperties = include.Split('.');

            childType = parentType.GetProperty(includeProperties[0], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).PropertyType;

            includeMethodInfo    = IncludeMethodInfo.MakeGenericMethod(parentType, childType);
            methodCallExpression = Expression.Call(
                includeMethodInfo,
                query.Expression,
                CreateExpression(parentType, includeProperties[0]));

            resultQuery = new IncludableQueryable <T, object>(query.Provider.CreateQuery <T>(methodCallExpression));

            for (int i = 1; i < includeProperties.Length; i++)
            {
                parentType = childType;
                if (parentType.IsGenericType)
                {
                    parentType            = parentType.GetGenericArguments().First();
                    childType             = parentType.GetProperty(includeProperties[i], BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance).PropertyType;
                    thenIncludeMethodInfo = ThenIncludeAfterCollectionMethodInfo.MakeGenericMethod(typeof(T), parentType, childType);
                    methodCallExpression  = Expression.Call(
                        thenIncludeMethodInfo,
                        resultQuery.Expression,
                        CreateExpression(parentType, includeProperties[i]));
                }

                resultQuery = new IncludableQueryable <T, object>(resultQuery.Provider.CreateQuery <T>(methodCallExpression));
            }

            return(resultQuery);
        }
예제 #4
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);
            }
        }