diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index 4902eac65d0..5f3580b165e 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -875,7 +875,7 @@ protected virtual void ValidateTypeMappings( { _ = property.GetCurrentValueComparer(); // Will throw if there is no way to compare } - + var providerComparer = property.GetProviderValueComparer(); if (providerComparer == null) { diff --git a/src/EFCore/Storage/CoreTypeMapping.cs b/src/EFCore/Storage/CoreTypeMapping.cs index d80348b4984..368914fb408 100644 --- a/src/EFCore/Storage/CoreTypeMapping.cs +++ b/src/EFCore/Storage/CoreTypeMapping.cs @@ -200,7 +200,7 @@ public virtual ValueComparer ProviderValueComparer this, static c => (c.Converter?.ProviderClrType ?? c.ClrType) == c.ClrType ? c.KeyComparer - : ValueComparer.CreateDefault(c.Converter?.ProviderClrType ?? c.ClrType, favorStructuralComparisons: true)); + : ValueComparer.CreateDefault(c.Converter!.ProviderClrType, favorStructuralComparisons: true)); /// /// Returns a new copy of this type mapping with the given diff --git a/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs b/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs index 2fa187fea19..f3f63e1b31b 100644 --- a/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs +++ b/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs @@ -33,6 +33,50 @@ protected class WithNonComparableKey public NotComparable Id { get; set; } } + [ConditionalFact] + public virtual void Detects_noncomparable_key_property_with_comparer() + { + var modelBuilder = CreateConventionModelBuilder(); + + modelBuilder.Entity( + eb => + { + eb.Property(e => e.Id).HasConversion(typeof(NotComparable), typeof(CustomValueComparer)); + eb.HasKey(e => e.Id); + }); + + VerifyError( + CoreStrings.NonComparableKeyType(nameof(WithNonComparableKey), nameof(WithNonComparableKey.Id), nameof(NotComparable)), + modelBuilder); + } + + [ConditionalFact] + public virtual void Detects_noncomparable_key_property_with_provider_comparer() + { + var modelBuilder = CreateConventionModelBuilder(); + + modelBuilder.Entity( + eb => + { + eb.Property(e => e.Id).HasConversion( + typeof(CastingConverter), null, typeof(CustomValueComparer)); + eb.HasKey(e => e.Id); + }); + + VerifyError( + CoreStrings.NonComparableKeyTypes( + nameof(WithNonComparableKey), nameof(WithNonComparableKey.Id), nameof(NotComparable), nameof(NotComparable)), + modelBuilder); + } + + public class CustomValueComparer : ValueComparer // Doesn't implement IComparer + { + public CustomValueComparer() + : base(false) + { + } + } + [ConditionalFact] public virtual void Detects_unique_index_property_which_cannot_be_compared() { @@ -1396,7 +1440,7 @@ public virtual void Detects_incompatible_discriminator_value() VerifyError(CoreStrings.DiscriminatorValueIncompatible("1", nameof(A), "int"), modelBuilder); } - + [ConditionalFact] public virtual void Detects_missing_discriminator_value_on_base() { @@ -1412,7 +1456,7 @@ public virtual void Detects_missing_discriminator_value_on_base() entityA.SetDiscriminatorProperty(entityA.AddProperty("D", typeof(int))); entityA.RemoveDiscriminatorValue(); - + entityC.SetDiscriminatorValue(1); VerifyError(CoreStrings.NoDiscriminatorValue(entityA.DisplayName()), modelBuilder); @@ -1433,7 +1477,7 @@ public virtual void Detects_missing_discriminator_value_on_leaf() entityAbstract.SetDiscriminatorProperty(entityAbstract.AddProperty("D", typeof(int))); entityAbstract.SetDiscriminatorValue(0); - + entityGeneric.RemoveDiscriminatorValue(); VerifyError(CoreStrings.NoDiscriminatorValue(entityGeneric.DisplayName()), modelBuilder); diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericTest.cs index a7727e3a1ae..0af74d7cd1c 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericTest.cs @@ -517,14 +517,14 @@ public override TestPropertyBuilder HasField(string fieldName) public override TestPropertyBuilder UsePropertyAccessMode(PropertyAccessMode propertyAccessMode) => Wrap(PropertyBuilder.UsePropertyAccessMode(propertyAccessMode)); - public override TestPropertyBuilder HasConversion() - => Wrap(PropertyBuilder.HasConversion()); + public override TestPropertyBuilder HasConversion() + => Wrap(PropertyBuilder.HasConversion()); - public override TestPropertyBuilder HasConversion(ValueComparer? valueComparer) - => Wrap(PropertyBuilder.HasConversion(valueComparer)); + public override TestPropertyBuilder HasConversion(ValueComparer? valueComparer) + => Wrap(PropertyBuilder.HasConversion(valueComparer)); - public override TestPropertyBuilder HasConversion(ValueComparer? valueComparer, ValueComparer? providerComparerType) - => Wrap(PropertyBuilder.HasConversion(valueComparer, providerComparerType)); + public override TestPropertyBuilder HasConversion(ValueComparer? valueComparer, ValueComparer? providerComparerType) + => Wrap(PropertyBuilder.HasConversion(valueComparer, providerComparerType)); public override TestPropertyBuilder HasConversion( Expression> convertToProviderExpression, diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericTest.cs index 72339a741ec..0461bb82e30 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericTest.cs @@ -597,14 +597,14 @@ public override TestPropertyBuilder HasField(string fieldName) public override TestPropertyBuilder UsePropertyAccessMode(PropertyAccessMode propertyAccessMode) => Wrap(PropertyBuilder.UsePropertyAccessMode(propertyAccessMode)); - public override TestPropertyBuilder HasConversion() - => Wrap(PropertyBuilder.HasConversion()); + public override TestPropertyBuilder HasConversion() + => Wrap(PropertyBuilder.HasConversion(typeof(TConversion))); - public override TestPropertyBuilder HasConversion(ValueComparer? valueComparer) - => Wrap(PropertyBuilder.HasConversion(valueComparer)); + public override TestPropertyBuilder HasConversion(ValueComparer? valueComparer) + => Wrap(PropertyBuilder.HasConversion(typeof(TConversion), valueComparer)); - public override TestPropertyBuilder HasConversion(ValueComparer? valueComparer, ValueComparer? providerComparerType) - => Wrap(PropertyBuilder.HasConversion(valueComparer, providerComparerType)); + public override TestPropertyBuilder HasConversion(ValueComparer? valueComparer, ValueComparer? providerComparerType) + => Wrap(PropertyBuilder.HasConversion(typeof(TConversion), valueComparer, providerComparerType)); public override TestPropertyBuilder HasConversion( Expression> convertToProviderExpression, diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderTestBase.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderTestBase.cs index bd7ee7ac3d5..f796983df96 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderTestBase.cs @@ -400,9 +400,9 @@ public abstract TestPropertyBuilder HasValueGeneratorFactory HasField(string fieldName); public abstract TestPropertyBuilder UsePropertyAccessMode(PropertyAccessMode propertyAccessMode); - public abstract TestPropertyBuilder HasConversion(); - public abstract TestPropertyBuilder HasConversion(ValueComparer? valueComparer); - public abstract TestPropertyBuilder HasConversion(ValueComparer? valueComparer, ValueComparer? providerComparerType); + public abstract TestPropertyBuilder HasConversion(); + public abstract TestPropertyBuilder HasConversion(ValueComparer? valueComparer); + public abstract TestPropertyBuilder HasConversion(ValueComparer? valueComparer, ValueComparer? providerComparerType); public abstract TestPropertyBuilder HasConversion( Expression> convertToProviderExpression,