Beispiel #1
0
        private IEnumerable <IncludeLoadTree> CreateIncludeLoadTrees(QueryModel queryModel, bool shouldThrow)
        {
            var querySourceTracingExpressionVisitor
                = _querySourceTracingExpressionVisitorFactory.Create();

            var includeLoadTrees = new List <IncludeLoadTree>();

            foreach (var includeResultOperator in _includeResultOperators.ToArray())
            {
                var querySourceReferenceExpression
                    = querySourceTracingExpressionVisitor
                      .FindResultQuerySourceReferenceExpression(
                          queryModel.GetOutputExpression(),
                          includeResultOperator.QuerySource);

                if (querySourceReferenceExpression == null)
                {
                    continue;
                }

                if (querySourceReferenceExpression.Type.IsGrouping() &&
                    querySourceTracingExpressionVisitor.OriginGroupByQueryModel != null)
                {
                    querySourceReferenceExpression
                        = querySourceTracingExpressionVisitor
                          .FindResultQuerySourceReferenceExpression(
                              querySourceTracingExpressionVisitor.OriginGroupByQueryModel.GetOutputExpression(),
                              includeResultOperator.QuerySource);

                    _targetQueryModel = querySourceTracingExpressionVisitor.OriginGroupByQueryModel;
                }

                if (querySourceReferenceExpression?.Type.IsGrouping() != false)
                {
                    continue;
                }

                var includeLoadTree
                    = includeLoadTrees
                      .SingleOrDefault(
                          t => ReferenceEquals(
                              t.QuerySourceReferenceExpression, querySourceReferenceExpression));

                if (includeLoadTree == null)
                {
                    includeLoadTrees.Add(includeLoadTree = new IncludeLoadTree(querySourceReferenceExpression));
                }

                if (!TryPopulateIncludeLoadTree(includeResultOperator, includeLoadTree, shouldThrow))
                {
                    includeLoadTrees.Remove(includeLoadTree);
                    continue;
                }

                _queryCompilationContext.Logger.NavigationIncluded(includeResultOperator);
                _includeResultOperators.Remove(includeResultOperator);
            }

            return(includeLoadTrees);
        }
Beispiel #2
0
        private static bool WalkNavigations(
            IEntityType entityType,
            IReadOnlyList <string> navigationPropertyPaths,
            IncludeLoadTree includeLoadTree,
            bool shouldThrow)
        {
            var longestMatchFound
                = WalkNavigationsInternal(
                      entityType,
                      navigationPropertyPaths,
                      includeLoadTree,
                      new Stack <INavigation>(),
                      (0, entityType));

            if (longestMatchFound.Depth < navigationPropertyPaths.Count)
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(
                              CoreStrings.IncludeBadNavigation(
                                  navigationPropertyPaths[longestMatchFound.Depth],
                                  longestMatchFound.EntityType.DisplayName()));
                }

                return(false);
            }

            return(true);
        }
Beispiel #3
0
        private bool TryPopulateIncludeLoadTree(
            IncludeResultOperator includeResultOperator,
            IncludeLoadTree includeLoadTree,
            bool shouldThrow)
        {
            if (includeResultOperator.NavigationPaths != null)
            {
                foreach (var navigationPath in includeResultOperator.NavigationPaths)
                {
                    includeLoadTree.AddLoadPath(navigationPath);
                }

                return(true);
            }

            IEntityType entityType = null;

            if (includeResultOperator.PathFromQuerySource is QuerySourceReferenceExpression qsre)
            {
                entityType = _queryCompilationContext.FindEntityType(qsre.ReferencedQuerySource);
            }

            if (entityType == null)
            {
                entityType = _queryCompilationContext.Model.FindEntityType(includeResultOperator.PathFromQuerySource.Type);

                if (entityType == null)
                {
                    var pathFromSource = MemberAccessBindingExpressionVisitor.GetPropertyPath(
                        includeResultOperator.PathFromQuerySource, _queryCompilationContext, out qsre);

                    if (pathFromSource.Count > 0 &&
                        pathFromSource[pathFromSource.Count - 1] is INavigation navigation)
                    {
                        entityType = navigation.GetTargetType();
                    }
                }
            }

            if (entityType == null)
            {
                if (shouldThrow)
                {
                    throw new InvalidOperationException(
                              CoreStrings.IncludeNotSpecifiedDirectlyOnEntityType(
                                  includeResultOperator.ToString(),
                                  includeResultOperator.NavigationPropertyPaths.FirstOrDefault()));
                }

                return(false);
            }

            return(WalkNavigations(entityType, includeResultOperator.NavigationPropertyPaths, includeLoadTree, shouldThrow));
        }
Beispiel #4
0
        private IEnumerable <IncludeLoadTree> CreateIncludeLoadTrees(
            Expression targetExpression)
        {
            var querySourceTracingExpressionVisitor
                = _querySourceTracingExpressionVisitorFactory.Create();

            var includeLoadTrees = new List <IncludeLoadTree>();

            foreach (var includeResultOperator in _includeResultOperators.ToArray())
            {
                var navigationPath = includeResultOperator.GetNavigationPath(_queryCompilationContext);

                var querySourceReferenceExpression
                    = querySourceTracingExpressionVisitor
                      .FindResultQuerySourceReferenceExpression(
                          targetExpression,
                          includeResultOperator.QuerySource);

                if (querySourceReferenceExpression == null)
                {
                    continue;
                }

                var includeLoadTree
                    = includeLoadTrees
                      .SingleOrDefault(
                          t => ReferenceEquals(
                              t.QuerySourceReferenceExpression, querySourceReferenceExpression));

                if (includeLoadTree == null)
                {
                    includeLoadTrees.Add(includeLoadTree = new IncludeLoadTree(querySourceReferenceExpression));
                }

                includeLoadTree.AddLoadPath(navigationPath);

                _queryCompilationContext.Logger
                .LogDebug(
                    CoreEventId.IncludingNavigation,
                    () => CoreStrings.LogIncludingNavigation(includeResultOperator.DisplayString()));

                _includeResultOperators.Remove(includeResultOperator);
            }

            return(includeLoadTrees);
        }
Beispiel #5
0
        private IEnumerable <IncludeLoadTree> CreateIncludeLoadTrees(QueryModel queryModel)
        {
            var querySourceTracingExpressionVisitor
                = _querySourceTracingExpressionVisitorFactory.Create();

            var includeLoadTrees = new List <IncludeLoadTree>();

            foreach (var includeResultOperator in _includeResultOperators.ToArray())
            {
                var navigationPath = includeResultOperator.GetNavigationPath(_queryCompilationContext);

                var querySourceReferenceExpression
                    = querySourceTracingExpressionVisitor
                      .FindResultQuerySourceReferenceExpression(
                          queryModel.GetOutputExpression(),
                          includeResultOperator.QuerySource);

                if (querySourceReferenceExpression == null ||
                    navigationPath == null)
                {
                    continue;
                }

                var includeLoadTree
                    = includeLoadTrees
                      .SingleOrDefault(
                          t => ReferenceEquals(
                              t.QuerySourceReferenceExpression, querySourceReferenceExpression));

                if (includeLoadTree == null)
                {
                    includeLoadTrees.Add(includeLoadTree = new IncludeLoadTree(querySourceReferenceExpression));
                }

                includeLoadTree.AddLoadPath(navigationPath);

                _queryCompilationContext.Logger.NavigationIncluded(includeResultOperator);

                _includeResultOperators.Remove(includeResultOperator);
            }

            return(includeLoadTrees);
        }
Beispiel #6
0
        private static KeyValuePair <int, IEntityType> WalkNavigationsInternal(
            IEntityType entityType,
            IReadOnlyList <string> navigationPropertyPaths,
            IncludeLoadTree includeLoadTree,
            Stack <INavigation> stack,
            KeyValuePair <int, IEntityType> longestMatchFound)
        {
            var outboundNavigations
                = entityType.GetNavigations()
                  .Concat(entityType.GetDerivedTypes().SelectMany(et => et.GetDeclaredNavigations()))
                  .Where(n => navigationPropertyPaths.Count > stack.Count && n.Name == navigationPropertyPaths[stack.Count])
                  .ToList();

            if (outboundNavigations.Count == 0 &&
                stack.Count > 0)
            {
                includeLoadTree.AddLoadPath(stack.Reverse().ToArray());
                if (stack.Count > longestMatchFound.Key)
                {
                    longestMatchFound = new KeyValuePair <int, IEntityType>(stack.Count, entityType);
                }
            }
            else
            {
                foreach (var navigation in outboundNavigations)
                {
                    stack.Push(navigation);

                    longestMatchFound = WalkNavigationsInternal(navigation.GetTargetType(), navigationPropertyPaths, includeLoadTree, stack, longestMatchFound);

                    stack.Pop();
                }
            }

            return(longestMatchFound);
        }
Beispiel #7
0
 private static (int Depth, IEntityType EntityType) WalkNavigationsInternal(
     IEntityType entityType,
     IReadOnlyList <string> navigationPropertyPaths,
     IncludeLoadTree includeLoadTree,
     Stack <INavigation> stack,
     (int Depth, IEntityType EntityType) longestMatchFound)
Beispiel #8
0
        private static void WalkNavigations(IEntityType entityType, IReadOnlyList <string> navigationPropertyPaths, IncludeLoadTree includeLoadTree)
        {
            var longestMatchFound = WalkNavigationsInternal(entityType, navigationPropertyPaths, includeLoadTree, new Stack <INavigation>(), new KeyValuePair <int, IEntityType>(0, null));

            if (longestMatchFound.Key < navigationPropertyPaths.Count)
            {
                throw new InvalidOperationException(
                          CoreStrings.IncludeBadNavigation(navigationPropertyPaths[longestMatchFound.Key], longestMatchFound.Value.DisplayName()));
            }
        }