From 254c3e7748a95ec40c6a3ddf24cdc0866abe47aa Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Wed, 8 Jul 2020 11:01:04 -0700 Subject: [PATCH] Add more tests --- .../Metadata/Builders/EntityTypeBuilder`.cs | 13 +- .../Builders/OwnedNavigationBuilder.cs | 4 +- .../Builders/OwnedNavigationBuilder`.cs | 28 ++-- .../CosmosModelBuilderGenericTest.cs | 21 --- .../ModelBuilding/ManyToOneTestBase.cs | 16 +++ .../ModelBuilderNonGenericStringTest.cs | 15 +++ .../ModelBuilding/NonRelationshipTestBase.cs | 4 +- .../ModelBuilding/OneToManyTestBase.cs | 16 +++ .../ModelBuilding/OneToOneTestBase.cs | 16 +++ .../ModelBuilding/OwnedTypesTestBase.cs | 122 +++++++++++++++--- test/EFCore.Tests/ModelBuilding/TestModel.cs | 82 ++++++++---- 11 files changed, 254 insertions(+), 83 deletions(-) diff --git a/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs b/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs index 5808954caec..f7817f9b2aa 100644 --- a/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs +++ b/src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs @@ -853,11 +853,14 @@ private OwnedNavigationBuilder OwnsManyBuilder HasOne OwnsOneBui InternalForeignKeyBuilder relationship; using (var batch = DependentEntityType.Model.ConventionDispatcher.DelayConventions()) { - relationship = navigation.MemberInfo == null - ? targetTypeName == null - ? DependentEntityType.Builder.HasOwnership(typeof(TNewDependentEntity), navigation.Name, ConfigurationSource.Explicit) - : DependentEntityType.Builder.HasOwnership(targetTypeName, typeof(TNewDependentEntity), navigation.Name, ConfigurationSource.Explicit) - : DependentEntityType.Builder.HasOwnership( - typeof(TNewDependentEntity), (PropertyInfo)navigation.MemberInfo, ConfigurationSource.Explicit); + relationship = targetTypeName == null + ? navigation.MemberInfo == null + ? DependentEntityType.Builder.HasOwnership(typeof(TNewDependentEntity), navigation.Name, ConfigurationSource.Explicit) + : DependentEntityType.Builder.HasOwnership(typeof(TNewDependentEntity), navigation.MemberInfo, ConfigurationSource.Explicit) + : navigation.MemberInfo == null + ? DependentEntityType.Builder.HasOwnership(targetTypeName, typeof(TNewDependentEntity), navigation.Name, ConfigurationSource.Explicit) + : DependentEntityType.Builder.HasOwnership(targetTypeName, typeof(TNewDependentEntity), navigation.MemberInfo, ConfigurationSource.Explicit); + relationship.IsUnique(true, ConfigurationSource.Explicit); relationship = (InternalForeignKeyBuilder)batch.Run(relationship.Metadata).Builder; } @@ -812,12 +814,14 @@ private OwnedNavigationBuilder OwnsManyBuil InternalForeignKeyBuilder relationship; using (var batch = DependentEntityType.Model.ConventionDispatcher.DelayConventions()) { - relationship = navigation.MemberInfo == null - ? targetTypeName == null - ? DependentEntityType.Builder.HasOwnership(typeof(TNewRelatedEntity), navigation.Name, ConfigurationSource.Explicit) - : DependentEntityType.Builder.HasOwnership(targetTypeName, typeof(TNewRelatedEntity), navigation.Name, ConfigurationSource.Explicit) - : DependentEntityType.Builder.HasOwnership( - typeof(TNewRelatedEntity), (PropertyInfo)navigation.MemberInfo, ConfigurationSource.Explicit); + relationship = targetTypeName == null + ? navigation.MemberInfo == null + ? DependentEntityType.Builder.HasOwnership(typeof(TNewRelatedEntity), navigation.Name, ConfigurationSource.Explicit) + : DependentEntityType.Builder.HasOwnership(typeof(TNewRelatedEntity), navigation.MemberInfo, ConfigurationSource.Explicit) + : navigation.MemberInfo == null + ? DependentEntityType.Builder.HasOwnership(targetTypeName, typeof(TNewRelatedEntity), navigation.Name, ConfigurationSource.Explicit) + : DependentEntityType.Builder.HasOwnership(targetTypeName, typeof(TNewRelatedEntity), navigation.MemberInfo, ConfigurationSource.Explicit); + relationship.IsUnique(false, ConfigurationSource.Explicit); relationship = (InternalForeignKeyBuilder)batch.Run(relationship.Metadata).Builder; } diff --git a/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs b/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs index 7f37407d47b..d38df677d60 100644 --- a/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs +++ b/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs @@ -171,27 +171,6 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id_and_p Assert.Empty(entity.GetKeys().Where(k => k != entity.FindPrimaryKey())); } - public override void Can_add_shared_type_entity_type() - { - var modelBuilder = CreateModelBuilder(); - modelBuilder.Entity>("Shared1"); - - modelBuilder.Entity>("Shared2", b => b.IndexerProperty("Id")); - - var model = modelBuilder.Model; - Assert.Equal(2, model.GetEntityTypes().Count()); - - var shared1 = modelBuilder.Model.FindEntityType("Shared1"); - Assert.NotNull(shared1); - Assert.True(shared1.HasSharedClrType); - Assert.Equal(new [] { "Discriminator", "__id", "__jObject" }, shared1.GetProperties().Select(e => e.Name)); - - var shared2 = modelBuilder.Model.FindEntityType("Shared2"); - Assert.NotNull(shared2); - Assert.True(shared2.HasSharedClrType); - Assert.Equal(new[] { "Id", "Discriminator", "__id", "__jObject" }, shared2.GetProperties().Select(e => e.Name)); - } - protected override TestModelBuilder CreateModelBuilder() => CreateTestModelBuilder(CosmosTestHelpers.Instance); } diff --git a/test/EFCore.Tests/ModelBuilding/ManyToOneTestBase.cs b/test/EFCore.Tests/ModelBuilding/ManyToOneTestBase.cs index 93d649a35bf..80b1d83fef9 100644 --- a/test/EFCore.Tests/ModelBuilding/ManyToOneTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/ManyToOneTestBase.cs @@ -2002,6 +2002,22 @@ public virtual void Access_mode_can_be_overridden_at_entity_and_navigation_prope Assert.Equal(PropertyAccessMode.Field, dependent.Metadata.GetPropertyAccessMode()); Assert.Equal(PropertyAccessMode.Property, dependent.Metadata.FindNavigation("OneToManyPrincipal").GetPropertyAccessMode()); } + + [ConditionalFact] + public virtual void Navigation_to_shared_type() + { + var modelBuilder = CreateModelBuilder(); + + modelBuilder.Entity() + .HasMany("Shared1", e => e.SharedCollection) + .WithOne(); + + modelBuilder.Entity() + .HasMany("Shared2", e => e.SharedCollection) + .WithOne(); + + Assert.Equal(2, modelBuilder.Model.GetEntityTypes().Where(e => e.HasSharedClrType).Count()); + } } } } diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericStringTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericStringTest.cs index f81864c0ee7..a8b1e894473 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericStringTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericStringTest.cs @@ -51,6 +51,21 @@ public override void OwnedType_can_derive_from_Collection() public override void Can_configure_owned_type_collection_with_one_call_afterwards() { } + + //Shadow navigations not supported #3864 + public override void Can_use_shared_type_entity_type_with_owns_one_inside_owned_entity() + { + } + + //Shadow navigations not supported #3864 + public override void Can_use_shared_type_entity_type_with_owns_many_inside_owned_entity() + { + } + + //Shadow navigations not supported #3864 + public override void Can_use_shared_type_entity_type_with_has_one_inside_owned_entity() + { + } } public class NonGenericStringOneToManyType : OneToManyTestBase diff --git a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs index 672c5a6f026..a9c272b529f 100644 --- a/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/NonRelationshipTestBase.cs @@ -1555,12 +1555,12 @@ public virtual void Can_add_shared_type_entity_type() var shared1 = modelBuilder.Model.FindEntityType("Shared1"); Assert.NotNull(shared1); Assert.True(shared1.HasSharedClrType); - Assert.Empty(shared1.GetProperties()); + Assert.Null(shared1.FindProperty("Id")); var shared2 = modelBuilder.Model.FindEntityType("Shared2"); Assert.NotNull(shared2); Assert.True(shared2.HasSharedClrType); - Assert.Equal("Id", Assert.Single(shared2.GetProperties()).Name); + Assert.NotNull(shared2.FindProperty("Id")); } } } diff --git a/test/EFCore.Tests/ModelBuilding/OneToManyTestBase.cs b/test/EFCore.Tests/ModelBuilding/OneToManyTestBase.cs index e9303de9584..3229fd9825d 100644 --- a/test/EFCore.Tests/ModelBuilding/OneToManyTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/OneToManyTestBase.cs @@ -2577,6 +2577,22 @@ public virtual void Attempt_to_configure_Navigation_property_which_is_actually_a .UsePropertyAccessMode(PropertyAccessMode.Property) ).Message); } + + [ConditionalFact] + public virtual void Navigation_to_shared_type() + { + var modelBuilder = CreateModelBuilder(); + + modelBuilder.Entity() + .HasOne("Shared1", e => e.SharedReference) + .WithMany(); + + modelBuilder.Entity() + .HasOne("Shared2", e => e.SharedReference) + .WithMany(); + + Assert.Equal(2, modelBuilder.Model.GetEntityTypes().Where(e => e.HasSharedClrType).Count()); + } } } } diff --git a/test/EFCore.Tests/ModelBuilding/OneToOneTestBase.cs b/test/EFCore.Tests/ModelBuilding/OneToOneTestBase.cs index 7fb4445744b..aa621d7d67b 100644 --- a/test/EFCore.Tests/ModelBuilding/OneToOneTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/OneToOneTestBase.cs @@ -4056,6 +4056,22 @@ public virtual void Navigation_properties_can_set_access_mode_using_navigation_n Assert.Equal(PropertyAccessMode.Field, principal.FindNavigation("Dependent").GetPropertyAccessMode()); Assert.Equal(PropertyAccessMode.Property, dependent.FindNavigation("OneToOnePrincipal").GetPropertyAccessMode()); } + + [ConditionalFact] + public virtual void Navigation_to_shared_type() + { + var modelBuilder = CreateModelBuilder(); + + modelBuilder.Entity() + .HasOne("Shared1", e => e.SharedReference) + .WithOne(); + + modelBuilder.Entity() + .HasOne("Shared2", e => e.SharedReference) + .WithOne(); + + Assert.Equal(2, modelBuilder.Model.GetEntityTypes().Where(e => e.HasSharedClrType).Count()); + } } } } diff --git a/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs b/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs index 48e76aacf8c..128a3e7b85d 100644 --- a/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs @@ -1568,56 +1568,144 @@ public virtual void Attempt_to_create_OwnsOne_on_a_collection_throws() } [ConditionalFact] - public virtual void Can_use_shared_type_entity_type_with_owns_one_expression() + public virtual void Can_use_shared_type_entity_type_with_owns_one() { var modelBuider = CreateModelBuilder(); - modelBuider.Ignore(); - modelBuider.Ignore(); - modelBuider.Entity().OwnsOne("Shared1", e => e.Shared); - modelBuider.Entity().OwnsOne("Shared2", e => e.Shared, b => b.Ignore(e => e.Random)); + modelBuider.Entity().OwnsOne("Shared1", e => e.SharedReference); + modelBuider.Entity().OwnsOne("Shared2", e => e.SharedReference, b => b.Property(e => e.Random)); Assert.Collection(modelBuider.Model.GetEntityTypes(), - t => { Assert.Equal(typeof(Customer).FullName, t.Name); }, - t => { Assert.Equal(typeof(Order).FullName, t.Name); }, + t => { Assert.Equal(typeof(SharedHolderAlpha).FullName, t.Name); }, + t => { Assert.Equal(typeof(SharedHolderBeta).FullName, t.Name); }, t => { Assert.Equal("Shared1", t.Name); Assert.True(t.HasSharedClrType); - Assert.NotNull(t.FindProperty("Random")); + Assert.Null(t.FindProperty("Random")); }, t => { Assert.Equal("Shared2", t.Name); Assert.True(t.HasSharedClrType); - Assert.Null(t.FindProperty("Random")); + Assert.NotNull(t.FindProperty("Random")); }); } [ConditionalFact] - public virtual void Can_use_shared_type_entity_type_with_owns_one_string() + public virtual void Can_use_shared_type_entity_type_with_owns_many() { var modelBuider = CreateModelBuilder(); - modelBuider.Ignore(); - modelBuider.Ignore(); - modelBuider.Entity().OwnsOne("Shared1", "Shared"); - modelBuider.Entity().OwnsOne("Shared2", "Shared", b => b.Ignore(e => e.Random)); + modelBuider.Entity().OwnsMany("Shared1", e => e.SharedCollection); + modelBuider.Entity().OwnsMany("Shared2", e => e.SharedCollection, b => b.Property(e => e.Random)); Assert.Collection(modelBuider.Model.GetEntityTypes(), - t => { Assert.Equal(typeof(Customer).FullName, t.Name); }, - t => { Assert.Equal(typeof(Order).FullName, t.Name); }, + t => { Assert.Equal(typeof(SharedHolderAlpha).FullName, t.Name); }, + t => { Assert.Equal(typeof(SharedHolderBeta).FullName, t.Name); }, t => { Assert.Equal("Shared1", t.Name); Assert.True(t.HasSharedClrType); + Assert.Null(t.FindProperty("Random")); + }, + t => + { + Assert.Equal("Shared2", t.Name); + Assert.True(t.HasSharedClrType); Assert.NotNull(t.FindProperty("Random")); + }); + } + + [ConditionalFact] + public virtual void Can_use_shared_type_entity_type_with_owns_one_inside_owned_entity() + { + var modelBuider = CreateModelBuilder(); + + modelBuider.Entity().OwnsOne( + e => e.SharedReference, + b => + { + b.OwnsOne("Shared1", e => e.NestedReference); + b.OwnsOne("Shared2", e => e.NestedReference, b => b.Property(e => e.NestedRandom)); + }); + + Assert.Collection(modelBuider.Model.GetEntityTypes(), + t => { Assert.Equal(typeof(SharedHolderAlpha).FullName, t.Name); }, + t => { Assert.Equal(typeof(SharedTypeEntityType).FullName, t.Name); }, + t => + { + Assert.Equal("Shared1", t.Name); + Assert.True(t.HasSharedClrType); + Assert.Null(t.FindProperty("NestedRandom")); }, t => { Assert.Equal("Shared2", t.Name); Assert.True(t.HasSharedClrType); - Assert.Null(t.FindProperty("Random")); + Assert.NotNull(t.FindProperty("NestedRandom")); + }); + } + + [ConditionalFact] + public virtual void Can_use_shared_type_entity_type_with_owns_many_inside_owned_entity() + { + var modelBuider = CreateModelBuilder(); + + modelBuider.Entity().OwnsOne( + e => e.SharedReference, + b => + { + b.OwnsMany("Shared1", e => e.NestedCollection); + b.OwnsMany("Shared2", e => e.NestedCollection, b => b.Property(e => e.NestedRandom)); + }); + + Assert.Collection(modelBuider.Model.GetEntityTypes(), + t => { Assert.Equal(typeof(SharedHolderAlpha).FullName, t.Name); }, + t => { Assert.Equal(typeof(SharedTypeEntityType).FullName, t.Name); }, + t => + { + Assert.Equal("Shared1", t.Name); + Assert.True(t.HasSharedClrType); + Assert.Null(t.FindProperty("NestedRandom")); + }, + t => + { + Assert.Equal("Shared2", t.Name); + Assert.True(t.HasSharedClrType); + Assert.NotNull(t.FindProperty("NestedRandom")); + }); + } + + [ConditionalFact] + public virtual void Can_use_shared_type_entity_type_with_has_one_inside_owned_entity() + { + var modelBuider = CreateModelBuilder(); + + modelBuider.Entity().OwnsOne( + e => e.SharedReference, + b => + { + b.HasOne("Shared1", e => e.ReferenceNavigation).WithOne(); + b.HasOne("Shared2", e => e.ReferenceNavigation).WithMany(); + }); + + modelBuider.Entity("Shared2").Property(e => e.Value); + + Assert.Collection(modelBuider.Model.GetEntityTypes(), + t => { Assert.Equal(typeof(SharedHolderAlpha).FullName, t.Name); }, + t => { Assert.Equal(typeof(SharedTypeEntityType).FullName, t.Name); }, + t => + { + Assert.Equal("Shared1", t.Name); + Assert.True(t.HasSharedClrType); + Assert.Null(t.FindProperty("Value")); + }, + t => + { + Assert.Equal("Shared2", t.Name); + Assert.True(t.HasSharedClrType); + Assert.NotNull(t.FindProperty("Value")); }); } } diff --git a/test/EFCore.Tests/ModelBuilding/TestModel.cs b/test/EFCore.Tests/ModelBuilding/TestModel.cs index 8b8f10466d1..e0eb6406388 100644 --- a/test/EFCore.Tests/ModelBuilding/TestModel.cs +++ b/test/EFCore.Tests/ModelBuilding/TestModel.cs @@ -98,14 +98,6 @@ protected class Customer public ICollection SomeOrders { get; set; } public CustomerDetails Details { get; set; } - - [NotMapped] - public SharedTypeEntityType Shared { get; set; } - } - - protected class SharedTypeEntityType - { - public int Random { get; set; } } [NotMapped] @@ -152,9 +144,6 @@ protected class Order : INotifyPropertyChanged public OrderCombination OrderCombination { get; set; } public OrderDetails Details { get; set; } public ICollection Products { get; set; } - [NotMapped] - public SharedTypeEntityType Shared { get; set; } - public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { @@ -940,7 +929,7 @@ private class OwnedOneToManyNavDependent public OneToManyNavPrincipalOwner OneToManyOwner { get; set; } } - public class OwnerOfOwnees + protected class OwnerOfOwnees { public string Id { get; private set; } @@ -948,22 +937,22 @@ public class OwnerOfOwnees public Ownee1 Ownee1 { get; private set; } } - public class Ownee1 + protected class Ownee1 { public Ownee3 NewOwnee3 { get; private set; } } - public class Ownee2 + protected class Ownee2 { public Ownee3 Ownee3 { get; private set; } } - public class Ownee3 + protected class Ownee3 { public string Name { get; private set; } } - public class OneToManyPrincipalWithField + protected class OneToManyPrincipalWithField { public int Id; public Guid AlternateKey; @@ -972,7 +961,7 @@ public class OneToManyPrincipalWithField public IEnumerable Dependents; } - public class OneToOnePrincipalWithField + protected class OneToOnePrincipalWithField { public int Id; public string Name; @@ -980,7 +969,7 @@ public class OneToOnePrincipalWithField public DependentWithField Dependent; } - public class ManyToManyPrincipalWithField + protected class ManyToManyPrincipalWithField { public int Id; public string Name; @@ -997,7 +986,7 @@ protected class ManyToManyJoinWithFields public DependentWithField DependentWithField { get; set; } } - public class DependentWithField + protected class DependentWithField { public int DependentWithFieldId; @@ -1009,7 +998,7 @@ public class DependentWithField public List ManyToManyPrincipals { get; set; } } - public class OneToManyOwnerWithField + protected class OneToManyOwnerWithField { public int Id; public Guid AlternateKey; @@ -1018,7 +1007,7 @@ public class OneToManyOwnerWithField public List OwnedDependents { get; set; } } - public class OneToManyOwnedWithField + protected class OneToManyOwnedWithField { public string FirstName; public string LastName; @@ -1027,7 +1016,7 @@ public class OneToManyOwnedWithField public OneToManyOwnerWithField OneToManyOwner { get; set; } } - public class OneToOneOwnerWithField + protected class OneToOneOwnerWithField { public int Id; public Guid AlternateKey; @@ -1036,7 +1025,7 @@ public class OneToOneOwnerWithField public OneToOneOwnedWithField OwnedDependent { get; set; } } - public class OneToOneOwnedWithField + protected class OneToOneOwnedWithField { public string FirstName; public string LastName; @@ -1046,7 +1035,7 @@ public class OneToOneOwnedWithField } - public class AutomaticManyToManyA + protected class AutomaticManyToManyA { public int Id { get; set; } public string Name { get; set; } @@ -1055,12 +1044,55 @@ public class AutomaticManyToManyA } - public class AutomaticManyToManyB + protected class AutomaticManyToManyB { public int Id { get; set; } public string Name { get; set; } public List As { get; set; } } + + protected class SharedHolderAlpha + { + public int Id { get; set; } + [NotMapped] + public SharedTypeEntityType SharedReference { get; set; } + [NotMapped] + public List SharedCollection { get; set; } + } + + protected class SharedHolderBeta + { + public int Id { get; set; } + [NotMapped] + public SharedTypeEntityType SharedReference { get; set; } + [NotMapped] + public List SharedCollection { get; set; } + } + + protected class SharedTypeEntityType + { + [NotMapped] + public int Random { get; set; } + [NotMapped] + public SharedNestedOwnedEntityType NestedReference { get; set; } + [NotMapped] + public List NestedCollection { get; set; } + [NotMapped] + public NestedReference ReferenceNavigation { get; set; } + } + + protected class SharedNestedOwnedEntityType + { + [NotMapped] + public int NestedRandom { get; set; } + } + + protected class NestedReference + { + public int Id { get; set; } + [NotMapped] + public string Value { get; set; } + } } }