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)); }
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); }