From 86e0dfd5c18c12e3f4a252f97d9e0ae22839aa2a Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Tue, 16 Aug 2022 19:10:58 -0700 Subject: [PATCH] Validate that GetContainingPropertyName() is null iff IsDocumentRoot() Fixes #27342 --- .../Internal/CosmosModelValidator.cs | 6 ++++++ .../Properties/CosmosStrings.Designer.cs | 8 ++++++++ src/EFCore.Cosmos/Properties/CosmosStrings.resx | 3 +++ .../Infrastructure/CosmosModelValidatorTest.cs | 14 ++++++++++++-- 4 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs index fb674031523..7b39d2df637 100644 --- a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs +++ b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs @@ -67,6 +67,12 @@ protected virtual void ValidateSharedContainerCompatibility( entityType.DisplayName(), ownership.PrincipalEntityType.DisplayName(), container)); } + if (entityType.GetContainingPropertyName() != null) + { + throw new InvalidOperationException(CosmosStrings.ContainerContainingPropertyConflict( + entityType.DisplayName(), container, entityType.GetContainingPropertyName())); + } + if (!containers.TryGetValue(container, out var mappedTypes)) { mappedTypes = new List(); diff --git a/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs b/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs index 197e81d7a42..f1894064ad1 100644 --- a/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs +++ b/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs @@ -43,6 +43,14 @@ public static string CanConnectNotSupported public static string ConnectionStringConflictingConfiguration => GetString("ConnectionStringConflictingConfiguration"); + /// + /// The entity type '{entityType}' is mapped to the container '{container}' but it is also configured as being contained in property '{property}'. + /// + public static string ContainerContainingPropertyConflict(object? entityType, object? container, object? property) + => string.Format( + GetString("ContainerContainingPropertyConflict", nameof(entityType), nameof(container), nameof(property)), + entityType, container, property); + /// /// Cosmos-specific methods can only be used when the context is using the Cosmos provider. /// diff --git a/src/EFCore.Cosmos/Properties/CosmosStrings.resx b/src/EFCore.Cosmos/Properties/CosmosStrings.resx index 314782e698f..5e7d04b82a2 100644 --- a/src/EFCore.Cosmos/Properties/CosmosStrings.resx +++ b/src/EFCore.Cosmos/Properties/CosmosStrings.resx @@ -126,6 +126,9 @@ Both the connection string and CredentialToken, account key or account endpoint were specified. Specify only one set of connection details. + + The entity type '{entityType}' is mapped to the container '{container}' but it is also configured as being contained in property '{property}'. + Cosmos-specific methods can only be used when the context is using the Cosmos provider. diff --git a/test/EFCore.Cosmos.Tests/Infrastructure/CosmosModelValidatorTest.cs b/test/EFCore.Cosmos.Tests/Infrastructure/CosmosModelValidatorTest.cs index 99fce63f1b9..10a9f28006c 100644 --- a/test/EFCore.Cosmos.Tests/Infrastructure/CosmosModelValidatorTest.cs +++ b/test/EFCore.Cosmos.Tests/Infrastructure/CosmosModelValidatorTest.cs @@ -277,7 +277,7 @@ public virtual void Detects_property_and_embedded_type_mapped_to_same_property() public virtual void Detects_owned_type_mapped_to_a_container() { var modelBuilder = CreateConventionModelBuilder(); - modelBuilder.Entity(); + modelBuilder.Entity().ToContainer("Orders"); modelBuilder.Entity( ob => { @@ -290,6 +290,16 @@ public virtual void Detects_owned_type_mapped_to_a_container() nameof(OrderDetails), nameof(Order), "Details"), modelBuilder); } + [ConditionalFact] + public virtual void Detects_conflicting_containing_property() + { + var modelBuilder = CreateConventionModelBuilder(); + modelBuilder.Entity().ToContainer("Orders"); + modelBuilder.Entity().ToContainer("Orders").Metadata.SetContainingPropertyName("Prop"); + + VerifyError(CosmosStrings.ContainerContainingPropertyConflict(nameof(Order), "Orders", "Prop"), modelBuilder); + } + [ConditionalFact] public virtual void Detects_missing_discriminator() { @@ -297,7 +307,7 @@ public virtual void Detects_missing_discriminator() modelBuilder.Entity().ToContainer("Orders").HasNoDiscriminator(); modelBuilder.Entity().ToContainer("Orders"); - VerifyError(CosmosStrings.NoDiscriminatorProperty(typeof(Customer).Name, "Orders"), modelBuilder); + VerifyError(CosmosStrings.NoDiscriminatorProperty(nameof(Customer), "Orders"), modelBuilder); } [ConditionalFact]