diff --git a/eng/Versions.props b/eng/Versions.props index 253fefa1435..914fd31db50 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -49,7 +49,7 @@ 1.20.0 1.4.0 1.15.1 - 3.0.2 + 3.0.3 2.3.2 diff --git a/src/EFCore/EFCore.baseline.json b/src/EFCore/EFCore.baseline.json index b52c3b307fa..bffa286d455 100644 --- a/src/EFCore/EFCore.baseline.json +++ b/src/EFCore/EFCore.baseline.json @@ -3851,7 +3851,10 @@ "Member": "static string ConflictingKeylessAndPrimaryKeyAttributes(object? entity);" }, { - "Member": "static string ConflictingPropertyOrNavigation(object? member, object? type, object? conflictingType);" + "Member": "static string ConflictingPropertyOrNavigationOnBaseType(object? member, object? type, object? conflictingMemberKind, object? conflictingType);" + }, + { + "Member": "static string ConflictingPropertyOrNavigationWithKind(object? member, object? type, object? conflictingMemberKind);" }, { "Member": "static string ConflictingRelationshipConversions(object? entityType, object? property, object? valueConversion, object? conflictingValueConversion);" diff --git a/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder.cs b/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder.cs index dcb060b5d62..f9d66346752 100644 --- a/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/ReferenceNavigationBuilder.cs @@ -238,8 +238,8 @@ private InternalForeignKeyBuilder WithOneBuilder(MemberIdentity reference) && ReferenceName == referenceName) { throw new InvalidOperationException( - CoreStrings.ConflictingPropertyOrNavigation( - referenceName, RelatedEntityType.DisplayName(), RelatedEntityType.DisplayName())); + CoreStrings.ConflictingPropertyOrNavigationWithKind( + referenceName, RelatedEntityType.DisplayName(), "navigation")); } var pointsToPrincipal = !foreignKey.IsSelfReferencing() diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index 6cc6fcf2bef..a5b15b86883 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -1451,16 +1451,14 @@ public virtual Navigation AddNavigation(MemberIdentity navigationMember, Foreign } throw new InvalidOperationException( - CoreStrings.ConflictingPropertyOrNavigation( - name, DisplayName(), duplicateNavigation.DeclaringEntityType.DisplayName())); + duplicateNavigation.FormatConflictingMemberMessage(name, this)); } var duplicateProperty = FindMembersInHierarchy(name).FirstOrDefault(); if (duplicateProperty != null) { throw new InvalidOperationException( - CoreStrings.ConflictingPropertyOrNavigation( - name, DisplayName(), ((IReadOnlyTypeBase)duplicateProperty.DeclaringType).DisplayName())); + duplicateProperty.FormatConflictingMemberMessage(name, this)); } Check.DebugAssert( @@ -1633,8 +1631,7 @@ public virtual IEnumerable GetNavigations() if (duplicateProperty != null) { throw new InvalidOperationException( - CoreStrings.ConflictingPropertyOrNavigation( - name, DisplayName(), duplicateProperty.DeclaringType.DisplayName())); + duplicateProperty.FormatConflictingMemberMessage(name, this)); } if (memberInfo != null) @@ -2286,9 +2283,7 @@ public virtual ServiceProperty AddServiceProperty( if (duplicateMember != null) { throw new InvalidOperationException( - CoreStrings.ConflictingPropertyOrNavigation( - name, DisplayName(), - ((IReadOnlyTypeBase)duplicateMember.DeclaringType).DisplayName())); + duplicateMember.FormatConflictingMemberMessage(name, this)); } ValidateClrMember(name, memberInfo, false); diff --git a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs index 72f06816d57..b7f507e130d 100644 --- a/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalEntityTypeBuilder.cs @@ -541,8 +541,7 @@ public override void RemoveMembersInHierarchy(string propertyName, Configuration if (conflictingNavigation.GetConfigurationSource() == ConfigurationSource.Explicit) { throw new InvalidOperationException( - CoreStrings.ConflictingPropertyOrNavigation( - propertyName, Metadata.DisplayName(), conflictingNavigation.DeclaringEntityType.DisplayName())); + conflictingNavigation.FormatConflictingMemberMessage(propertyName, Metadata)); } var foreignKey = conflictingNavigation.ForeignKey; diff --git a/src/EFCore/Metadata/Internal/PropertyBaseExtensions.cs b/src/EFCore/Metadata/Internal/PropertyBaseExtensions.cs index 19b27dace99..0588611cc57 100644 --- a/src/EFCore/Metadata/Internal/PropertyBaseExtensions.cs +++ b/src/EFCore/Metadata/Internal/PropertyBaseExtensions.cs @@ -338,6 +338,56 @@ or PropertyAccessMode.FieldDuringConstruction return false; } + /// + /// Builds the message for the diagnostic that fires when a member conflicts with an existing + /// member on the structural type or one of its base types. The kind of the conflicting member + /// is humanized via so the user-facing message uses stable + /// labels like "property", "complex property", "navigation", "skip navigation", or + /// "service property" regardless of whether the conflicting member came from a model or a + /// runtime model. + /// + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public static string FormatConflictingMemberMessage( + this IReadOnlyPropertyBase conflictingMember, + string newMemberName, + IReadOnlyTypeBase owningType) + { + var conflictingMemberKind = GetMemberKindString(conflictingMember); + var owningTypeDisplayName = owningType.DisplayName(); + + // Compare the actual metadata instances rather than display names to avoid false positives when + // two distinct types share a simple name (e.g. same name in different namespaces or hierarchies). + return conflictingMember.DeclaringType == owningType + ? CoreStrings.ConflictingPropertyOrNavigationWithKind(newMemberName, owningTypeDisplayName, conflictingMemberKind) + : CoreStrings.ConflictingPropertyOrNavigationOnBaseType( + newMemberName, + owningTypeDisplayName, + conflictingMemberKind, + ((IReadOnlyTypeBase)conflictingMember.DeclaringType).DisplayName()); + } + + /// + /// Returns a human-readable label for the kind of the given member (e.g. "property", + /// "complex property", "navigation", "skip navigation", "service property"). Used to build + /// user-facing diagnostic messages without coupling the message text to internal CLR class + /// names (such as RuntimeProperty or SkipNavigation). + /// + private static string GetMemberKindString(IReadOnlyPropertyBase member) + => member switch + { + IReadOnlyComplexProperty => "complex property", + IReadOnlySkipNavigation => "skip navigation", + IReadOnlyNavigation => "navigation", + IReadOnlyServiceProperty => "service property", + IReadOnlyProperty => "property", + _ => member.GetType().Name + }; + private static string GetNoFieldErrorMessage(IPropertyBase propertyBase) => propertyBase.DeclaringType switch { diff --git a/src/EFCore/Metadata/Internal/TypeBase.cs b/src/EFCore/Metadata/Internal/TypeBase.cs index 0cfe3f25afc..3b3fe513e32 100644 --- a/src/EFCore/Metadata/Internal/TypeBase.cs +++ b/src/EFCore/Metadata/Internal/TypeBase.cs @@ -634,9 +634,7 @@ private void CheckDiscriminatorProperty(Property? property) if (conflictingMember != null) { throw new InvalidOperationException( - CoreStrings.ConflictingPropertyOrNavigation( - name, DisplayName(), - ((IReadOnlyTypeBase)conflictingMember.DeclaringType).DisplayName())); + conflictingMember.FormatConflictingMemberMessage(name, this)); } if (memberInfo != null) @@ -1082,9 +1080,7 @@ public virtual IReadOnlyDictionary GetRuntimeFields() if (conflictingMember != null) { throw new InvalidOperationException( - CoreStrings.ConflictingPropertyOrNavigation( - name, DisplayName(), - conflictingMember.DeclaringType.DisplayName())); + conflictingMember.FormatConflictingMemberMessage(name, this)); } if (memberInfo != null) diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index bf9d212a078..7f65927b402 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -877,12 +877,20 @@ public static string ConflictingKeylessAndPrimaryKeyAttributes(object? entity) entity); /// - /// The property or navigation '{member}' cannot be added to the '{type}' type because a property or navigation with the same name already exists on the '{conflictingType}' type. + /// The member '{member}' cannot be added to the '{type}' type because a {conflictingMemberKind} with the same name already exists on the '{conflictingType}' type. Remove the existing {conflictingMemberKind} first. /// - public static string ConflictingPropertyOrNavigation(object? member, object? type, object? conflictingType) + public static string ConflictingPropertyOrNavigationOnBaseType(object? member, object? type, object? conflictingMemberKind, object? conflictingType) => string.Format( - GetString("ConflictingPropertyOrNavigation", nameof(member), nameof(type), nameof(conflictingType)), - member, type, conflictingType); + GetString("ConflictingPropertyOrNavigationOnBaseType", nameof(member), nameof(type), nameof(conflictingMemberKind), nameof(conflictingType)), + member, type, conflictingMemberKind, conflictingType); + + /// + /// The member '{member}' cannot be added to the '{type}' type because a {conflictingMemberKind} with the same name already exists. Remove the existing {conflictingMemberKind} first. + /// + public static string ConflictingPropertyOrNavigationWithKind(object? member, object? type, object? conflictingMemberKind) + => string.Format( + GetString("ConflictingPropertyOrNavigationWithKind", nameof(member), nameof(type), nameof(conflictingMemberKind)), + member, type, conflictingMemberKind); /// /// The property '{entityType}.{property}' participates in several relationship chains that have conflicting conversions: '{valueConversion}' and '{conflictingValueConversion}'. diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index 673e2719b39..ba84a1aebd1 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -438,8 +438,11 @@ The entity type '{entity}' has both [Keyless] and [PrimaryKey] attributes; one must be removed. - - The property or navigation '{member}' cannot be added to the '{type}' type because a property or navigation with the same name already exists on the '{conflictingType}' type. + + The member '{member}' cannot be added to the '{type}' type because a {conflictingMemberKind} with the same name already exists on the '{conflictingType}' type. Remove the existing {conflictingMemberKind} first. + + + The member '{member}' cannot be added to the '{type}' type because a {conflictingMemberKind} with the same name already exists. Remove the existing {conflictingMemberKind} first. The property '{entityType}.{property}' participates in several relationship chains that have conflicting conversions: '{valueConversion}' and '{conflictingValueConversion}'. diff --git a/test/EFCore.Specification.Tests/ModelBuilding/ModelBuilderTest.OneToOne.cs b/test/EFCore.Specification.Tests/ModelBuilding/ModelBuilderTest.OneToOne.cs index 5c446e28541..9cedb5df661 100644 --- a/test/EFCore.Specification.Tests/ModelBuilding/ModelBuilderTest.OneToOne.cs +++ b/test/EFCore.Specification.Tests/ModelBuilding/ModelBuilderTest.OneToOne.cs @@ -3050,7 +3050,7 @@ public virtual void Throws_on_duplicate_navigation_when_self_referencing() var modelBuilder = CreateModelBuilder(); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("SelfRef1", nameof(SelfRef), nameof(SelfRef)), + CoreStrings.ConflictingPropertyOrNavigationWithKind("SelfRef1", nameof(SelfRef), "navigation"), Assert.Throws(() => modelBuilder.Entity().HasOne(e => e.SelfRef1).WithOne(e => e.SelfRef1)).Message); } diff --git a/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.BaseType.cs b/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.BaseType.cs index 55a33981625..13d94f1e9ab 100644 --- a/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.BaseType.cs +++ b/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.BaseType.cs @@ -370,7 +370,7 @@ public void Adding_property_throws_when_parent_type_has_property_with_same_name( b.BaseType = a; Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("G", typeof(B).Name, typeof(A).Name), + CoreStrings.ConflictingPropertyOrNavigationOnBaseType("G", typeof(B).Name, "property", typeof(A).Name), Assert.Throws(() => b.AddProperty("G")).Message); } @@ -389,7 +389,7 @@ public void Adding_property_throws_when_grandparent_type_has_property_with_same_ d.BaseType = c; Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("G", typeof(D).Name, typeof(A).Name), + CoreStrings.ConflictingPropertyOrNavigationOnBaseType("G", typeof(D).Name, "property", typeof(A).Name), Assert.Throws(() => d.AddProperty("G")).Message); } @@ -406,7 +406,7 @@ public void Adding_property_throws_when_child_type_has_property_with_same_name() b.AddProperty(A.GProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("G", typeof(A).Name, typeof(B).Name), + CoreStrings.ConflictingPropertyOrNavigationOnBaseType("G", typeof(A).Name, "property", typeof(B).Name), Assert.Throws(() => a.AddProperty(A.GProperty)).Message); } @@ -426,7 +426,7 @@ public void Adding_property_throws_when_grandchild_type_has_property_with_same_n d.AddProperty(A.GProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("G", typeof(A).Name, typeof(D).Name), + CoreStrings.ConflictingPropertyOrNavigationOnBaseType("G", typeof(A).Name, "property", typeof(D).Name), Assert.Throws(() => a.AddProperty(A.GProperty)).Message); } diff --git a/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.cs b/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.cs index baa296d820e..7180c5b7039 100644 --- a/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/EntityTypeTest.cs @@ -952,7 +952,7 @@ public void Adding_a_new_navigation_with_a_name_that_conflicts_with_a_property_t orderType.AddProperty("Customer"); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("Customer", typeof(Order).Name, typeof(Order).Name), + CoreStrings.ConflictingPropertyOrNavigationWithKind("Customer", typeof(Order).Name, "property"), Assert.Throws(() => customerForeignKey.SetDependentToPrincipal("Customer")).Message); } @@ -970,7 +970,7 @@ public void Adding_a_new_navigation_with_a_name_that_conflicts_with_a_service_pr orderType.AddServiceProperty(Order.CustomerProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Order.Customer), nameof(Order), nameof(Order)), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Order.Customer), nameof(Order), "service property"), Assert.Throws(() => customerForeignKey.SetDependentToPrincipal(nameof(Order.Customer))).Message); } @@ -1154,7 +1154,7 @@ public void Throws_when_adding_same_self_referencing_navigation_twice() fk.SetPrincipalToDependent(SelfRef.SelfRef1Property); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(SelfRef.SelfRef1), typeof(SelfRef).Name, typeof(SelfRef).Name), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(SelfRef.SelfRef1), typeof(SelfRef).Name, "navigation"), Assert.Throws(() => fk.SetDependentToPrincipal(SelfRef.SelfRef1Property)).Message); } @@ -1363,7 +1363,7 @@ public void Adding_skip_navigation_with_a_name_that_conflicts_with_another_skip_ navigation.SetForeignKey(orderProductForeignKey); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Order.Products), typeof(Order).Name, typeof(Order).Name), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Order.Products), typeof(Order).Name, "skip navigation"), Assert.Throws(() => orderEntity.AddSkipNavigation( nameof(Order.Products), null, null, productEntity, true, false)).Message); @@ -1388,7 +1388,7 @@ public void Adding_skip_navigation_with_a_name_that_conflicts_with_a_navigation_ customerForeignKey.SetPrincipalToDependent(nameof(Order.Products)); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Order.Products), typeof(Order).Name, typeof(Order).Name), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Order.Products), typeof(Order).Name, "navigation"), Assert.Throws(() => orderEntity.AddSkipNavigation( nameof(Order.Products), null, null, productEntity, true, false)).Message); @@ -1410,7 +1410,7 @@ public void Adding_skip_navigation_with_a_name_that_conflicts_with_a_property_th orderEntity.AddProperty(nameof(Order.Products)); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Order.Products), typeof(Order).Name, typeof(Order).Name), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Order.Products), typeof(Order).Name, "property"), Assert.Throws(() => orderEntity.AddSkipNavigation( nameof(Order.Products), null, null, productEntity, true, false)).Message); @@ -1432,7 +1432,7 @@ public void Adding_skip_navigation_with_a_name_that_conflicts_with_a_service_pro orderEntity.AddServiceProperty(Order.ProductsProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Order.Products), typeof(Order).Name, typeof(Order).Name), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Order.Products), typeof(Order).Name, "service property"), Assert.Throws(() => orderEntity.AddSkipNavigation( nameof(Order.Products), null, null, productEntity, true, false)).Message); @@ -2046,7 +2046,7 @@ public void Adding_a_new_property_with_a_name_that_already_exists_throws() entityType.AddProperty(Customer.IdProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("Id", typeof(Customer).Name, typeof(Customer).Name), + CoreStrings.ConflictingPropertyOrNavigationWithKind("Id", typeof(Customer).Name, "property"), Assert.Throws(() => entityType.AddProperty("Id")).Message); } @@ -2064,7 +2064,7 @@ public void Adding_a_new_property_with_a_name_that_conflicts_with_a_navigation_t customerForeignKey.SetDependentToPrincipal(Order.CustomerProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("Customer", typeof(Order).Name, typeof(Order).Name), + CoreStrings.ConflictingPropertyOrNavigationWithKind("Customer", typeof(Order).Name, "navigation"), Assert.Throws(() => orderType.AddProperty("Customer")).Message); } @@ -2082,7 +2082,7 @@ public void Adding_a_new_property_with_a_name_that_conflicts_with_a_service_prop customerForeignKey.SetDependentToPrincipal(Order.CustomerProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Order.Customer), nameof(Order), nameof(Order)), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Order.Customer), nameof(Order), "navigation"), Assert.Throws(() => orderType.AddServiceProperty(Order.CustomerProperty)).Message); } @@ -2094,7 +2094,7 @@ public void Adding_a_new_service_property_with_a_name_that_conflicts_with_a_prop entityType.AddProperty(Customer.OrdersProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Customer.Orders), nameof(Customer), nameof(Customer)), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Customer.Orders), nameof(Customer), "property"), Assert.Throws(() => entityType.AddServiceProperty(Customer.OrdersProperty)).Message); } @@ -2112,7 +2112,7 @@ public void Adding_a_new_service_property_with_a_name_that_conflicts_with_a_navi customerForeignKey.SetDependentToPrincipal(Order.CustomerProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Order.Customer), nameof(Order), nameof(Order)), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Order.Customer), nameof(Order), "navigation"), Assert.Throws(() => orderType.AddServiceProperty(Order.CustomerProperty)).Message); } @@ -2124,7 +2124,7 @@ public void Adding_a_new_service_property_with_a_name_that_already_exists_throws entityType.AddServiceProperty(Customer.OrdersProperty); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation(nameof(Customer.Orders), nameof(Customer), nameof(Customer)), + CoreStrings.ConflictingPropertyOrNavigationWithKind(nameof(Customer.Orders), nameof(Customer), "service property"), Assert.Throws(() => entityType.AddServiceProperty(Customer.OrdersProperty)).Message); } @@ -2202,7 +2202,7 @@ public void AddIndexerProperty_throws_when_entitytype_have_property_with_same_na entityType.AddProperty("Nation", typeof(string)); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation("Nation", entityType.DisplayName(), entityType.DisplayName()), + CoreStrings.ConflictingPropertyOrNavigationWithKind("Nation", entityType.DisplayName(), "property"), Assert.Throws(() => entityType.AddIndexerProperty("Nation", typeof(string))).Message); Assert.Equal( diff --git a/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs b/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs index e96a0e82c7f..7b56e19f017 100644 --- a/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs +++ b/test/EFCore.Tests/Metadata/Internal/InternalEntityTypeBuilderTest.cs @@ -1667,8 +1667,8 @@ public void Property_throws_for_navigation() ConfigurationSource.Explicit); Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation( - nameof(Order.Customer), nameof(Order), nameof(Order)), + CoreStrings.ConflictingPropertyOrNavigationWithKind( + nameof(Order.Customer), nameof(Order), "navigation"), Assert.Throws(() => dependentEntityBuilder .Property(Order.CustomerProperty, ConfigurationSource.Explicit)).Message); } @@ -2487,9 +2487,23 @@ private void VerifyOverrideMembers( } else { + var conflictingKind = firstMemberType switch + { + MemberType.Property => "property", + MemberType.ComplexProperty => "complex property", + MemberType.ServiceProperty => "service property", + MemberType.Navigation => "navigation", + MemberType.SkipNavigation => "skip navigation", + _ => throw new InvalidOperationException() + }; + var declaringTypeName = firstEntityTypeBuilder.Metadata.DisplayName(); + Assert.Equal( - CoreStrings.ConflictingPropertyOrNavigation( - nameof(Order.Products), nameof(SpecialOrder), firstEntityTypeBuilder.Metadata.DisplayName()), + declaringTypeName == nameof(SpecialOrder) + ? CoreStrings.ConflictingPropertyOrNavigationWithKind( + nameof(Order.Products), nameof(SpecialOrder), conflictingKind) + : CoreStrings.ConflictingPropertyOrNavigationOnBaseType( + nameof(Order.Products), nameof(SpecialOrder), conflictingKind, declaringTypeName), Assert.Throws(() => ConfigureMember(secondEntityTypeBuilder, secondMemberType, secondSource)) .Message);