Exemple #1
0
        private (Expression operand, NavigationExpansionExpressionState state) ApplyIncludes(NavigationExpansionExpression navigationExpansionExpression)
        {
            var includeFinder = new PendingIncludeFindingVisitor();

            includeFinder.Visit(navigationExpansionExpression.State.PendingSelector.Body);

            var includeRewriter = new PendingSelectorIncludeRewriter();
            var rewrittenBody   = includeRewriter.Visit(navigationExpansionExpression.State.PendingSelector.Body);

            if (navigationExpansionExpression.State.PendingSelector.Body != rewrittenBody)
            {
                navigationExpansionExpression.State.PendingSelector      = Expression.Lambda(rewrittenBody, navigationExpansionExpression.State.PendingSelector.Parameters[0]);
                navigationExpansionExpression.State.ApplyPendingSelector = true;
            }

            if (includeFinder.PendingIncludes.Count > 0)
            {
                var result = (source : navigationExpansionExpression.Operand, parameter : navigationExpansionExpression.State.CurrentParameter);
                foreach (var pendingIncludeNode in includeFinder.PendingIncludes)
                {
                    result = NavigationExpansionHelpers.AddNavigationJoin(
                        result.source,
                        result.parameter,
                        pendingIncludeNode.Value,
                        pendingIncludeNode.Key,
                        navigationExpansionExpression.State,
                        new List <INavigation>(),
                        include: true);
                }

                var pendingSelector = navigationExpansionExpression.State.PendingSelector;
                if (navigationExpansionExpression.State.CurrentParameter != result.parameter)
                {
                    var pendingSelectorBody = new ExpressionReplacingVisitor(navigationExpansionExpression.State.CurrentParameter, result.parameter).Visit(navigationExpansionExpression.State.PendingSelector.Body);
                    pendingSelector = Expression.Lambda(pendingSelectorBody, result.parameter);
                }

                var newState = new NavigationExpansionExpressionState(
                    result.parameter,
                    navigationExpansionExpression.State.SourceMappings,
                    pendingSelector,
                    applyPendingSelector: true,
                    navigationExpansionExpression.State.PendingOrderings,
                    navigationExpansionExpression.State.PendingIncludeChain,
                    navigationExpansionExpression.State.PendingCardinalityReducingOperator,
                    navigationExpansionExpression.State.PendingTags,
                    navigationExpansionExpression.State.CustomRootMappings,
                    navigationExpansionExpression.State.MaterializeCollectionNavigation);

                return(operand : result.source, state : newState);
            }

            return(operand : navigationExpansionExpression.Operand, state : navigationExpansionExpression.State);
        }
Exemple #2
0
        protected override Expression VisitExtension(Expression extensionExpression)
        {
            if (extensionExpression is NavigationBindingExpression navigationBindingExpression)
            {
                var result = navigationBindingExpression.RootParameter.BuildPropertyAccess(navigationBindingExpression.NavigationTreeNode.ToMapping);

                return(result);
            }

            if (extensionExpression is NavigationExpansionRootExpression navigationExpansionRootExpression)
            {
                return(Visit(navigationExpansionRootExpression.Unwrap()));
            }

            if (extensionExpression is NavigationExpansionExpression navigationExpansionExpression)
            {
                var includeResult = ApplyIncludes(navigationExpansionExpression);
                var state         = includeResult.state;
                var result        = Visit(includeResult.operand);

                if (!state.ApplyPendingSelector &&
                    state.PendingOrderings.Count == 0 &&
                    state.PendingTags.Count == 0 &&
                    state.PendingCardinalityReducingOperator == null &&
                    state.MaterializeCollectionNavigation == null)
                {
                    return(result);
                }

                var parameter = Expression.Parameter(result.Type.GetSequenceType());

                foreach (var pendingOrdering in state.PendingOrderings)
                {
                    var remappedKeySelectorBody = new ExpressionReplacingVisitor(pendingOrdering.keySelector.Parameters[0], state.CurrentParameter).Visit(pendingOrdering.keySelector.Body);
                    var newSelectorBody         = new NavigationPropertyUnbindingVisitor(state.CurrentParameter).Visit(remappedKeySelectorBody);
                    var newSelector             = Expression.Lambda(newSelectorBody, state.CurrentParameter);
                    var orderingMethod          = pendingOrdering.method.MakeGenericMethod(state.CurrentParameter.Type, newSelectorBody.Type);
                    result = Expression.Call(orderingMethod, result, newSelector);
                }

                if (state.ApplyPendingSelector)
                {
                    var pendingSelector         = (LambdaExpression) new NavigationPropertyUnbindingVisitor(state.CurrentParameter).Visit(state.PendingSelector);
                    var pendingSelectorBodyType = pendingSelector.Type.GetGenericArguments()[1];

                    var pendingSelectMathod = result.Type.IsGenericType && (result.Type.GetGenericTypeDefinition() == typeof(IEnumerable <>) || result.Type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable <>))
                        ? LinqMethodHelpers.EnumerableSelectMethodInfo.MakeGenericMethod(parameter.Type, pendingSelectorBodyType)
                        : LinqMethodHelpers.QueryableSelectMethodInfo.MakeGenericMethod(parameter.Type, pendingSelectorBodyType);

                    result    = Expression.Call(pendingSelectMathod, result, pendingSelector);
                    parameter = Expression.Parameter(result.Type.GetSequenceType());
                }

                if (state.PendingTags.Count > 0)
                {
                    var withTagMethodInfo = EntityFrameworkQueryableExtensions.TagWithMethodInfo.MakeGenericMethod(parameter.Type);
                    foreach (var pendingTag in state.PendingTags)
                    {
                        result = Expression.Call(withTagMethodInfo, result, Expression.Constant(pendingTag));
                    }
                }

                if (state.PendingCardinalityReducingOperator != null)
                {
                    var terminatingOperatorMethodInfo = state.PendingCardinalityReducingOperator.MakeGenericMethod(parameter.Type);

                    result = Expression.Call(terminatingOperatorMethodInfo, result);
                }

                if (state.MaterializeCollectionNavigation != null)
                {
                    var entityType = state.MaterializeCollectionNavigation.ClrType.IsGenericType
                        ? state.MaterializeCollectionNavigation.ClrType.GetGenericArguments()[0]
                        : state.MaterializeCollectionNavigation.GetTargetType().ClrType;

                    result = Expression.Call(
                        NavigationExpansionHelpers.MaterializeCollectionNavigationMethodInfo.MakeGenericMethod(
                            state.MaterializeCollectionNavigation.ClrType,
                            entityType),
                        result,
                        Expression.Constant(state.MaterializeCollectionNavigation));
                }

                if (navigationExpansionExpression.Type != result.Type && navigationExpansionExpression.Type.IsGenericType)
                {
                    if (navigationExpansionExpression.Type.GetGenericTypeDefinition() == typeof(IOrderedQueryable <>))
                    {
                        var toOrderedQueryableMethodInfo = ToOrderedQueryableMethod.MakeGenericMethod(parameter.Type);

                        return(Expression.Call(toOrderedQueryableMethodInfo, result));
                    }
                    else if (navigationExpansionExpression.Type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable <>))
                    {
                        var toOrderedEnumerableMethodInfo = ToOrderedEnumerableMethod.MakeGenericMethod(parameter.Type);

                        return(Expression.Call(toOrderedEnumerableMethodInfo, result));
                    }
                }

                return(result);
            }

            return(base.VisitExtension(extensionExpression));
        }
Exemple #3
0
        protected override Expression VisitExtension(Expression extensionExpression)
        {
            switch (extensionExpression)
            {
            case NavigationBindingExpression navigationBindingExpression:
                return(navigationBindingExpression.RootParameter.BuildPropertyAccess(
                           navigationBindingExpression.NavigationTreeNode.ToMapping));

            case NavigationExpansionRootExpression navigationExpansionRootExpression:
                return(Visit(navigationExpansionRootExpression.Unwrap()));

            case NavigationExpansionExpression navigationExpansionExpression:
            {
                var(result, state) = ApplyIncludes(navigationExpansionExpression);
                result             = Visit(result);

                if (!state.ApplyPendingSelector &&
                    state.PendingOrderings.Count == 0 &&
                    state.PendingCardinalityReducingOperator == null &&
                    state.MaterializeCollectionNavigation == null)
                {
                    return(result);
                }

                var parameterType = result.Type.GetSequenceType();

                foreach (var pendingOrdering in state.PendingOrderings)
                {
                    var remappedKeySelectorBody = new ExpressionReplacingVisitor(pendingOrdering.keySelector.Parameters[0], state.CurrentParameter).Visit(pendingOrdering.keySelector.Body);
                    var newSelectorBody         = new NavigationPropertyUnbindingVisitor(state.CurrentParameter).Visit(remappedKeySelectorBody);
                    var newSelector             = Expression.Lambda(newSelectorBody, state.CurrentParameter);
                    var orderingMethod          = pendingOrdering.method.MakeGenericMethod(state.CurrentParameter.Type, newSelectorBody.Type);
                    result = Expression.Call(orderingMethod, result, newSelector);
                }

                if (state.ApplyPendingSelector)
                {
                    var pendingSelector         = (LambdaExpression) new NavigationPropertyUnbindingVisitor(state.CurrentParameter).Visit(state.PendingSelector);
                    var pendingSelectorBodyType = pendingSelector.Type.GetGenericArguments()[1];

                    var pendingSelectMethod = result.Type.IsGenericType && (result.Type.GetGenericTypeDefinition() == typeof(IEnumerable <>) || result.Type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable <>))
                                ? LinqMethodHelpers.EnumerableSelectMethodInfo.MakeGenericMethod(parameterType, pendingSelectorBodyType)
                                : LinqMethodHelpers.QueryableSelectMethodInfo.MakeGenericMethod(parameterType, pendingSelectorBodyType);

                    result        = Expression.Call(pendingSelectMethod, result, pendingSelector);
                    parameterType = result.Type.GetSequenceType();
                }

                if (state.PendingCardinalityReducingOperator != null)
                {
                    result = Expression.Call(state.PendingCardinalityReducingOperator, result);
                }

                if (state.MaterializeCollectionNavigation != null)
                {
                    result = new MaterializeCollectionNavigationExpression(result, state.MaterializeCollectionNavigation);
                }

                if (navigationExpansionExpression.Type != result.Type && navigationExpansionExpression.Type.IsGenericType)
                {
                    if (navigationExpansionExpression.Type.GetGenericTypeDefinition() == typeof(IOrderedQueryable <>))
                    {
                        var toOrderedQueryableMethodInfo = ToOrderedQueryableMethod.MakeGenericMethod(parameterType);

                        return(Expression.Call(toOrderedQueryableMethodInfo, result));
                    }

                    if (navigationExpansionExpression.Type.GetGenericTypeDefinition() == typeof(IOrderedEnumerable <>))
                    {
                        var toOrderedEnumerableMethodInfo = ToOrderedEnumerableMethod.MakeGenericMethod(parameterType);

                        return(Expression.Call(toOrderedEnumerableMethodInfo, result));
                    }
                }

                return(result);
            }
            }

            return(base.VisitExtension(extensionExpression));
        }