diff --git a/src/EntityFramework.Core/Query/EntityQueryModelVisitor.cs b/src/EntityFramework.Core/Query/EntityQueryModelVisitor.cs index 66915b9b4ca..ab7fdd6d0f0 100644 --- a/src/EntityFramework.Core/Query/EntityQueryModelVisitor.cs +++ b/src/EntityFramework.Core/Query/EntityQueryModelVisitor.cs @@ -394,27 +394,26 @@ var accessorLambda private IEnumerable BindChainedNavigations( IEnumerable boundNavigations, IReadOnlyList chainedNavigationProperties) { - var boundChainedNavigations = new List(); + var boundNavigationsList = boundNavigations.ToList(); if (chainedNavigationProperties != null) { - foreach ( - var navigation in - from propertyInfo in chainedNavigationProperties - // ReSharper disable once AssignNullToNotNullAttribute - let entityType = QueryCompilationContext.Model.FindEntityType(propertyInfo.DeclaringType) - select entityType?.FindNavigation(propertyInfo.Name)) + foreach (var propertyInfo in chainedNavigationProperties) { + var lastNavigation = boundNavigationsList.Last(); + var navigation = lastNavigation.GetTargetType().FindNavigation(propertyInfo.Name); + if (navigation == null) { return null; } - boundChainedNavigations.Add(navigation); + boundNavigationsList.Add(navigation); } + } - return boundNavigations.Concat(boundChainedNavigations); + return boundNavigationsList; } protected virtual void IncludeNavigations( diff --git a/test/EntityFramework.Core.FunctionalTests/InheritanceRelationshipsQueryFixtureBase.cs b/test/EntityFramework.Core.FunctionalTests/InheritanceRelationshipsQueryFixtureBase.cs index 3ae374c0ab0..a3c626f2cce 100644 --- a/test/EntityFramework.Core.FunctionalTests/InheritanceRelationshipsQueryFixtureBase.cs +++ b/test/EntityFramework.Core.FunctionalTests/InheritanceRelationshipsQueryFixtureBase.cs @@ -126,6 +126,16 @@ protected virtual void OnModelCreating(ModelBuilder modelBuilder) .WithOne(e => e.ParentCollection) .HasForeignKey(e => e.ParentCollectionId) .IsRequired(false); + + modelBuilder.Entity() + .HasOne(e => e.Reference) + .WithMany() + .IsRequired(false); + + modelBuilder.Entity() + .HasMany(e => e.Principals) + .WithOne() + .IsRequired(false); } } } diff --git a/test/EntityFramework.Core.FunctionalTests/InheritanceRelationshipsQueryTestBase.cs b/test/EntityFramework.Core.FunctionalTests/InheritanceRelationshipsQueryTestBase.cs index a8b11a88c44..5774752d276 100644 --- a/test/EntityFramework.Core.FunctionalTests/InheritanceRelationshipsQueryTestBase.cs +++ b/test/EntityFramework.Core.FunctionalTests/InheritanceRelationshipsQueryTestBase.cs @@ -750,6 +750,18 @@ public virtual void Nested_include_with_inheritance_collection_collection_revers } } + [Fact] + public virtual void Nested_include_collection_reference_on_non_entity_base() + { + using (var context = CreateContext()) + { + var query = context.ReferencedEntities.Include(e => e.Principals).ThenInclude(e => e.Reference); + var result = query.ToList(); + + Assert.Equal(2, result.Count); + } + } + protected InheritanceRelationshipsContext CreateContext() => Fixture.CreateContext(TestStore); protected InheritanceRelationshipsQueryTestBase(TFixture fixture) diff --git a/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/InheritanceRelationshipsContext.cs b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/InheritanceRelationshipsContext.cs index 8565dd516cc..bb7fefe6643 100644 --- a/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/InheritanceRelationshipsContext.cs +++ b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/InheritanceRelationshipsContext.cs @@ -29,5 +29,8 @@ public InheritanceRelationshipsContext(IServiceProvider serviceProvider, DbConte public DbSet CollectionsOnBase { get; set; } public DbSet CollectionsOnDerived { get; set; } public DbSet NestedCollections { get; set; } + + public DbSet PrincipalEntities { get; set; } + public DbSet ReferencedEntities { get; set; } } } diff --git a/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/InheritanceRelationshipsModelInitializer.cs b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/InheritanceRelationshipsModelInitializer.cs index f9882b82c72..b25d24772c0 100644 --- a/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/InheritanceRelationshipsModelInitializer.cs +++ b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/InheritanceRelationshipsModelInitializer.cs @@ -214,6 +214,25 @@ public static void Seed(InheritanceRelationshipsContext context) baseEntity2.DerivedSefReferenceOnBase = derivedEntity2; baseEntity3.DerivedSefReferenceOnBase = derivedEntity3; + var principalEntity1 = new PrincipalEntity(); + var principalEntity2 = new PrincipalEntity(); + + context.PrincipalEntities.AddRange(principalEntity1, principalEntity2); + + var referencedEntity1 = new ReferencedEntity + { + Principals = new List { principalEntity1 } + }; + var referencedEntity2 = new ReferencedEntity + { + Principals = new List { principalEntity2 } + }; + + context.ReferencedEntities.AddRange(referencedEntity1, referencedEntity2); + + principalEntity2.Reference = referencedEntity1; + principalEntity1.Reference = referencedEntity2; + context.SaveChanges(); } } diff --git a/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/NonEntityBase.cs b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/NonEntityBase.cs new file mode 100644 index 00000000000..365131c28d8 --- /dev/null +++ b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/NonEntityBase.cs @@ -0,0 +1,11 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Data.Entity.FunctionalTests.TestModels.InheritanceRelationships +{ + public class NonEntityBase + { + public int Id { get; set; } + public ReferencedEntity Reference { get; set; } + } +} diff --git a/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/PrincipalEntity.cs b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/PrincipalEntity.cs new file mode 100644 index 00000000000..3d1f442b282 --- /dev/null +++ b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/PrincipalEntity.cs @@ -0,0 +1,9 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +namespace Microsoft.Data.Entity.FunctionalTests.TestModels.InheritanceRelationships +{ + public class PrincipalEntity : NonEntityBase + { + } +} diff --git a/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/ReferencedEntity.cs b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/ReferencedEntity.cs new file mode 100644 index 00000000000..2e4cc39e6aa --- /dev/null +++ b/test/EntityFramework.Core.FunctionalTests/TestModels/InheritanceRelationships/ReferencedEntity.cs @@ -0,0 +1,14 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.Data.Entity.FunctionalTests.TestModels.InheritanceRelationships +{ + public class ReferencedEntity + { + public int Id { get; set; } + + public ICollection Principals { get; set; } + } +} diff --git a/test/EntityFramework.MicrosoftSqlServer.FunctionalTests/InheritanceRelationshipsQuerySqlServerTest.cs b/test/EntityFramework.MicrosoftSqlServer.FunctionalTests/InheritanceRelationshipsQuerySqlServerTest.cs index 28d1dd0245a..0ba4ddf56ea 100644 --- a/test/EntityFramework.MicrosoftSqlServer.FunctionalTests/InheritanceRelationshipsQuerySqlServerTest.cs +++ b/test/EntityFramework.MicrosoftSqlServer.FunctionalTests/InheritanceRelationshipsQuerySqlServerTest.cs @@ -956,6 +956,26 @@ WHERE [e].[Discriminator] IN ('NestedCollectionDerived', 'NestedCollectionBase') Sql); } + public override void Nested_include_collection_reference_on_non_entity_base() + { + base.Nested_include_collection_reference_on_non_entity_base(); + + Assert.Equal( + @"SELECT [e].[Id] +FROM [ReferencedEntity] AS [e] +ORDER BY [e].[Id] + +SELECT [p].[Id], [p].[ReferenceId], [p].[ReferencedEntityId], [r].[Id] +FROM [PrincipalEntity] AS [p] +INNER JOIN ( + SELECT DISTINCT [e].[Id] + FROM [ReferencedEntity] AS [e] +) AS [e] ON [p].[ReferencedEntityId] = [e].[Id] +LEFT JOIN [ReferencedEntity] AS [r] ON [p].[ReferenceId] = [r].[Id] +ORDER BY [e].[Id]", + Sql); + } + protected override void ClearLog() { }