Skip to content

Make type mapping generic so that it can create value comparers for NativeAOT - #38440

Merged
AndriySvyryd merged 2 commits into
mainfrom
Issue36817
Jun 22, 2026
Merged

Make type mapping generic so that it can create value comparers for NativeAOT#38440
AndriySvyryd merged 2 commits into
mainfrom
Issue36817

Conversation

@AndriySvyryd

Copy link
Copy Markdown
Member

Add static instance properties for values comparers and converts with default parameters

Fixes #36817

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves NativeAOT compatibility for compiled models by avoiding reflective creation of default value comparers/converters, and by making type mappings generic where the model CLR type is statically known.

Changes:

  • Add generic type-mapping base types (CoreTypeMapping<T>, RelationalTypeMapping<T>) and update built-in relational mappings to derive from them, enabling non-reflective default comparer creation.
  • Add cached default instances for common value converters and default comparers (ValueComparer<T>.Default*, various *.Instance) and adjust codegen/baselines to reuse these instead of emitting lambdas.
  • Update compiled-model scaffolding baselines and tests to remove redundant comparer emissions and to align with the new type-mapping/converter patterns.

Reviewed changes

Copilot reviewed 148 out of 182 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Vector_index/VectorIndexEntityEntityType.cs Baseline updated to use default type mapping/comparers instead of emitted lambdas.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Triggers/DataEntityType.cs Baseline updated to reduce emitted comparer/converter code.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Tpc_Sprocs/DependentBaseEntityType.cs Baseline updated to rely on default mapping instances.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/SpatialTypesTest/SpatialTypesEntityType.cs Baseline updated to omit redundant comparer cloning.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs Baseline updated to avoid explicit comparer construction.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs Baseline updated to use DefaultValueComparer<T> instances.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Key_sequence/DataEntityType.cs Baseline updated to omit explicit default comparer emission.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Key_HiLo_sequence/DataEntityType.cs Baseline updated to omit explicit default comparer emission.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Full_text_index/FullTextEntityEntityType.cs Baseline updated to omit redundant comparer/converter code.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Dynamic_schema/DataEntityType.cs Baseline updated to omit explicit comparer construction.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/DbFunctions/DbFunctionContextModelBuilder.cs Baseline updated to remove explicit comparers and reuse defaults.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/DbFunctions/DataEntityType.cs Baseline updated to omit explicit byte[] comparer construction.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Custom_function_type_mapping/FunctionTypeMappingContextModelBuilder.cs Baseline updated to omit explicit string comparer construction.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Custom_function_parameter_type_mapping/FunctionParameterTypeMappingContextModelBuilder.cs Baseline updated to omit explicit string comparer construction.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/CheckConstraints/DataEntityType.cs Baseline updated to omit explicit comparer construction.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs Baseline updated to use default comparers (incl. structural comparisons).
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs Baseline updated to omit explicit comparer construction.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs Baseline updated to use default enum converters/comparers.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs Baseline updated to use default comparers (incl. structural comparisons).
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DependentDerivedEntityType.cs Baseline updated to omit explicit comparer construction.
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DependentBaseEntityType.cs Baseline updated to use default enum converters/comparers.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/Triggers/DataEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs Baseline updated to use DefaultValueComparer<T> instances.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/Dynamic_schema/DataEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/DbFunctions/DbFunctionContextModelBuilder.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/DbFunctions/DataEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/Custom_function_type_mapping/FunctionTypeMappingContextModelBuilder.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/Custom_function_parameter_type_mapping/FunctionParameterTypeMappingContextModelBuilder.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/CheckConstraints/DataEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs Baseline updated to use default enum converters/comparers.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/DataEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/AutoIncrementEntityEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DependentBaseEntityType.cs Baseline updated to use default enum converters/comparers.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DataEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/AutoIncrementEntityEntityType.cs Baseline updated to remove explicit comparer emission.
test/EFCore.Specification.Tests/Scaffolding/CompiledModelTestBase.cs Renames helper method to avoid naming collision/clarify intent in tests.
test/EFCore.Relational.Tests/Metadata/RelationalModelTest.cs Updates test setup to avoid type-mapping clrType cloning and use converters instead.
test/EFCore.InMemory.FunctionalTests/Scaffolding/CompiledModelInMemoryTest.cs Updates test to use generic InMemoryTypeMapping<T>.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs Baseline updated to use generic in-memory type mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Self_referential_property/SelfReferentialEntityEntityType.cs Baseline updated to use generic in-memory mappings and default comparers.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/RelationshipCycles/DependentBaseEntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs Baseline updated to use DefaultValueComparer<T> instances.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Manual_lazy_loading/LazyPropertyEntityEntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Manual_lazy_loading/LazyPropertyDelegateEntityEntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Manual_lazy_loading/LazyConstructorEntityEntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Lazy_loading_proxies/LazyProxiesEntity2EntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Lazy_loading_proxies/LazyProxiesEntity1EntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Lazy_loading_manual/LazyProxiesEntity4EntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Lazy_loading_manual/LazyProxiesEntity3EntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Global_namespace/EntityType1.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Fully_qualified_model/ScaffoldingEntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Fully_qualified_model/IndexEntityType.cs Baseline updated to use generic in-memory mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Custom_value_converter/MyEntityEntityType.cs Baseline updated to use DefaultValueComparer<T> and generic mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Custom_value_comparer/MyEntityEntityType.cs Baseline updated to use generic mappings (custom comparer still emitted).
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Custom_type_mapping/MyEntityEntityType.cs Baseline updated to use generic mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Custom_provider_value_comparer/MyEntityEntityType.cs Baseline updated to use generic mappings (custom provider comparer still emitted).
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs Baseline updated to use generic mappings and JSON reader/writers.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs Baseline updated to use generic mappings.
test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs Baseline updated to use generic mappings and enum JSON reader/writers.
test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs Baseline updated to use generic Cosmos type mappings.
test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs Baseline updated to use DefaultValueComparer<T> instances and generic Cosmos mappings.
test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs Baseline updated to use generic Cosmos type mappings.
test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs Baseline updated to use default converters (GuidToStringConverter, EnumToNumberConverter) and default comparers.
src/EFCore/Storage/ValueConversion/UriToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/TimeSpanToTicksConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/TimeSpanToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/TimeOnlyToTicksConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/TimeOnlyToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToUriConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToTimeSpanConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToTimeOnlyConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToNumberConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToGuidConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToEnumConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToDateTimeOffsetConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToDateTimeConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToCharConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToBytesConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/StringToBoolConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/PhysicalAddressToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/PhysicalAddressToBytesConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/NumberToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/NumberToBytesConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/IPAddressToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/IPAddressToBytesConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/GuidToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/GuidToBytesConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/EnumToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/EnumToNumberConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/DateTimeToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/DateTimeToBinaryConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/DateTimeOffsetToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/DateTimeOffsetToBytesConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/DateTimeOffsetToBinaryConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/DateOnlyToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/CharToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/CastingConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/BytesToStringConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/BoolToZeroOneConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore/Storage/ValueConversion/BoolToStringConverter.cs Adds cached default converter instance and stabilizes default mapping hints instance.
src/EFCore/Storage/CoreTypeMapping`1.cs Introduces generic core type mapping base to create default comparers without reflection.
src/EFCore/Storage/CoreTypeMapping.cs Routes comparer creation through overridable methods and adds AOT-safe suppression points + default-comparer metadata.
src/EFCore/Design/Internal/ICSharpRuntimeAnnotationCodeGenerator.cs Simplifies Create signature to remove explicit comparer overrides.
src/EFCore/Design/ICSharpHelper.cs Updates lambda generation to operate on IPropertyBase to support complex property paths.
src/EFCore/ChangeTracking/ValueComparerExtensions.cs Updates default-comparer detection to match refactored default comparer types.
src/EFCore/ChangeTracking/ValueComparer`.cs Adds cached default comparer instances and uses Array.Clone() to avoid reflective ToArray generation.
src/EFCore/ChangeTracking/ValueComparer.cs Marks non-generic default-comparer creation as dynamic-code-requiring; reuses cached internal comparer instances.
src/EFCore.Relational/Storage/RelationalTypeMapping`1.cs Introduces generic relational mapping base for AOT-safe default comparer creation.
src/EFCore.Relational/Storage/RelationalTypeMapping.cs Avoids unnecessary clones when facets unchanged and removes ability to clone with different model CLR type.
src/EFCore.Relational/Storage/UShortTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<ushort>.
src/EFCore.Relational/Storage/ULongTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<ulong>.
src/EFCore.Relational/Storage/UIntTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<uint>.
src/EFCore.Relational/Storage/TimeSpanTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<TimeSpan>.
src/EFCore.Relational/Storage/TimeOnlyTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<TimeOnly>.
src/EFCore.Relational/Storage/StringTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<string>.
src/EFCore.Relational/Storage/ShortTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<short>.
src/EFCore.Relational/Storage/SByteTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<sbyte>.
src/EFCore.Relational/Storage/LongTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<long>.
src/EFCore.Relational/Storage/IntTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<int>.
src/EFCore.Relational/Storage/GuidTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<Guid>.
src/EFCore.Relational/Storage/FloatTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<float>.
src/EFCore.Relational/Storage/DoubleTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<double>.
src/EFCore.Relational/Storage/DecimalTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<decimal>.
src/EFCore.Relational/Storage/DateTimeTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<DateTime>.
src/EFCore.Relational/Storage/DateTimeOffsetTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<DateTimeOffset>.
src/EFCore.Relational/Storage/DateOnlyTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<DateOnly>.
src/EFCore.Relational/Storage/CharTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<char>.
src/EFCore.Relational/Storage/ByteTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<byte>.
src/EFCore.Relational/Storage/ByteArrayTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<byte[]>.
src/EFCore.Relational/Storage/BoolTypeMapping.cs Updates mapping to derive from RelationalTypeMapping<bool>.
src/EFCore.Relational/Design/Internal/RelationalCSharpRuntimeAnnotationCodeGenerator.cs Emits type-mapping clone arguments more selectively and centralizes comparer emission logic.
src/EFCore.InMemory/Storage/Internal/InMemoryTypeMappingSource.cs Creates common type mappings via generic path and limits reflection fallback for AOT scenarios.
src/EFCore.InMemory/Storage/Internal/InMemoryTypeMapping`1.cs Adds generic in-memory type mapping for AOT-safe default comparer creation.
src/EFCore.InMemory/Storage/Internal/InMemoryTypeMapping.cs Adjusts ctor visibility to support generic derived mapping type.
src/EFCore.Cosmos/Storage/Internal/ReadOnlyMemoryConverter.cs Adds cached default converter instance and reuses it via DefaultInfo.
src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs Creates common type mappings via generic path and limits reflection fallback for AOT scenarios.
src/EFCore.Cosmos/Storage/Internal/CosmosTypeMapping`1.cs Adds generic Cosmos type mapping for AOT-safe default comparer creation.
src/EFCore.Cosmos/Storage/Internal/CosmosTimeSpanTypeMapping.cs Updates mapping to derive from CosmosTypeMapping<TimeSpan>.
src/EFCore.Cosmos/Storage/Internal/CosmosTimeOnlyTypeMapping.cs Updates mapping to derive from CosmosTypeMapping<TimeOnly>.

Comment thread src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs Outdated
Comment thread src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs Outdated
@AndriySvyryd
AndriySvyryd marked this pull request as ready for review June 17, 2026 06:47
@AndriySvyryd
AndriySvyryd requested a review from a team as a code owner June 17, 2026 06:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 148 out of 182 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

src/EFCore.Relational/Storage/RelationalTypeMapping.cs:484

  • RelationalTypeMapping.Clone(...) also removed the clrType parameter, which is a breaking change for relational providers/extensions that previously relied on Clone(clrType: ...) to retarget a mapping. Consider retaining a compatibility overload (potentially [Obsolete]) which forwards to the new implementation, to avoid breaking external providers on upgrade.
    /// <summary>
    ///     Clones the type mapping to update any parameter if needed.
    /// </summary>
    /// <param name="mappingInfo">The mapping info containing the facets to use.</param>
    /// <param name="storeTypePostfix">The new postfix, or <see langword="null" /> to leave unchanged.</param>
    /// <param name="converter">The value converter, or <see langword="null" /> to leave unchanged.</param>
    /// <param name="comparer">The value comparer, or <see langword="null" /> to leave unchanged.</param>
    /// <param name="keyComparer">The key value comparer, or <see langword="null" /> to leave unchanged.</param>
    /// <param name="providerValueComparer">The provider value comparer, or <see langword="null" /> to leave unchanged.</param>
    /// <param name="elementMapping">The element mapping, or <see langword="null" /> to leave unchanged.</param>
    /// <param name="jsonValueReaderWriter">The JSON reader/writer, or <see langword="null" /> to leave unchanged.</param>
    /// <returns>The cloned mapping, or the original mapping if no clone was needed.</returns>
    public virtual RelationalTypeMapping Clone(
        in RelationalTypeMappingInfo? mappingInfo = null,
        ValueConverter? converter = null,
        ValueComparer? comparer = null,
        ValueComparer? keyComparer = null,
        ValueComparer? providerValueComparer = null,
        CoreTypeMapping? elementMapping = null,
        JsonValueReaderWriter? jsonValueReaderWriter = null,
        StoreTypePostfix? storeTypePostfix = null)
    {

Comment thread src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs
Comment thread src/EFCore/Storage/CoreTypeMapping.cs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 176 out of 228 changed files in this pull request and generated 6 comments.

Comment thread src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs Outdated
Comment thread test/EFCore.Relational.Tests/Metadata/RelationalModelTest.cs
Comment thread test/EFCore.Relational.Tests/Metadata/RelationalModelTest.cs
Comment thread src/EFCore/Storage/CoreTypeMapping.cs
Comment thread src/EFCore.Relational/Storage/RelationalTypeMapping.cs
Comment thread src/EFCore/Design/Internal/ICSharpRuntimeAnnotationCodeGenerator.cs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment on lines +255 to +276
=> clrType switch
{
_ when clrType == typeof(bool) => Create<bool>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(byte) => Create<byte>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(sbyte) => Create<sbyte>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(char) => Create<char>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(short) => Create<short>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(ushort) => Create<ushort>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(int) => Create<int>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(uint) => Create<uint>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(long) => Create<long>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(ulong) => Create<ulong>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(float) => Create<float>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(double) => Create<double>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(decimal) => Create<decimal>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(string) => Create<string>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(Guid) => Create<Guid>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(DateTime) => Create<DateTime>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(DateTimeOffset) => Create<DateTimeOffset>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ when clrType == typeof(DateOnly) => Create<DateOnly>(comparer, keyComparer, elementMapping, jsonValueReaderWriter),
_ => CreateMappingWithReflection(clrType, comparer, keyComparer, elementMapping, jsonValueReaderWriter)
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@roji loves it!

Copilot AI review requested due to automatic review settings June 19, 2026 20:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 178 out of 230 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

test/EFCore.Specification.Tests/Query/PrimitiveCollectionsQueryTestBase.cs:666

  • The base test method was renamed, but some provider test classes still override the old method names, which will cause compilation failures (no suitable method to override). For example:
  • test/EFCore.Sqlite.FunctionalTests/Query/PrimitiveCollectionsQuerySqliteTest.cs still overrides ...different_type_mapping()
  • test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs still overrides ...different_type_mapping()

These overrides should be renamed to match the new ...different_property() methods (both the Count and Contains variants).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 179 out of 232 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

src/EFCore.Relational/Storage/RelationalTypeMapping.cs:483

  • RelationalTypeMapping.Clone is a public API, and removing the clrType parameter is a breaking change for providers/extensions that relied on changing the model CLR type without introducing a converter. This also appears to force test-only workarounds (e.g. adding a dummy converter just to carry a different CLR type). Consider preserving this capability via an alternative API (or otherwise providing a supported migration path) while still enabling the NativeAOT-friendly generic type-mapping path.
    public virtual RelationalTypeMapping Clone(
        in RelationalTypeMappingInfo? mappingInfo = null,
        ValueConverter? converter = null,
        ValueComparer? comparer = null,
        ValueComparer? keyComparer = null,
        ValueComparer? providerValueComparer = null,
        CoreTypeMapping? elementMapping = null,
        JsonValueReaderWriter? jsonValueReaderWriter = null,
        StoreTypePostfix? storeTypePostfix = null)

Comment thread src/EFCore/Design/Internal/ICSharpRuntimeAnnotationCodeGenerator.cs
Comment thread test/EFCore.Relational.Tests/Metadata/RelationalModelTest.cs
Comment thread test/EFCore.Relational.Tests/Metadata/RelationalModelTest.cs
…ativeAOT

Add static instance properties for values comparers and converts with default parameters

Fixes #36817
Copilot AI review requested due to automatic review settings June 19, 2026 22:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 180 out of 241 changed files in this pull request and generated 2 comments.

Comment thread test/EFCore.Relational.Tests/Metadata/RelationalModelTest.cs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 180 out of 241 changed files in this pull request and generated 1 comment.

Comment thread src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs Outdated
@AndriySvyryd
AndriySvyryd merged commit 5dc20ee into main Jun 22, 2026
13 checks passed
@AndriySvyryd
AndriySvyryd deleted the Issue36817 branch June 22, 2026 15:11
@github-actions github-actions Bot added the api-review This PR or issue is introducing public API changes that need to be reviewed label Jun 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

API review baseline changes for src/EFCore.Relational/EFCore.Relational.baseline.json

Show diff

The diff below was generated by ApiChief between the base and the PR.

- class Microsoft.EntityFrameworkCore.Storage.BoolTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.BoolTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<bool>
- class Microsoft.EntityFrameworkCore.Storage.ByteArrayTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.ByteArrayTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<byte[]>
- class Microsoft.EntityFrameworkCore.Storage.ByteTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.ByteTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<byte>
- class Microsoft.EntityFrameworkCore.Storage.CharTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.CharTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<char>
- class Microsoft.EntityFrameworkCore.Storage.DateOnlyTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.DateOnlyTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<System.DateOnly>
- class Microsoft.EntityFrameworkCore.Storage.DateTimeOffsetTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.DateTimeOffsetTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<System.DateTimeOffset>
- class Microsoft.EntityFrameworkCore.Storage.DateTimeTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.DateTimeTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<System.DateTime>
- class Microsoft.EntityFrameworkCore.Storage.DecimalTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.DecimalTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<decimal>
- class Microsoft.EntityFrameworkCore.Storage.DoubleTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.DoubleTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<double>
- class Microsoft.EntityFrameworkCore.Storage.FloatTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.FloatTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<float>
- class Microsoft.EntityFrameworkCore.Storage.GuidTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.GuidTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<System.Guid>
- class Microsoft.EntityFrameworkCore.Storage.IntTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.IntTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<int>
- class Microsoft.EntityFrameworkCore.Storage.LongTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.LongTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<long>
  abstract class Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping : Microsoft.EntityFrameworkCore.Storage.CoreTypeMapping
- virtual RelationalTypeMapping Clone(in RelationalTypeMappingInfo? mappingInfo = null, Type? clrType = null, ValueConverter? converter = null,
-     ValueComparer? comparer = null, ValueComparer? keyComparer = null, ValueComparer? providerValueComparer = null, CoreTypeMapping? elementMapping = null,
-     JsonValueReaderWriter? jsonValueReaderWriter = null, StoreTypePostfix? storeTypePostfix = null);
+ virtual RelationalTypeMapping Clone(in RelationalTypeMappingInfo? mappingInfo = null, ValueConverter? converter = null, ValueComparer? comparer = null,
+     ValueComparer? keyComparer = null, ValueComparer? providerValueComparer = null, CoreTypeMapping? elementMapping = null,
+     JsonValueReaderWriter? jsonValueReaderWriter = null, StoreTypePostfix? storeTypePostfix = null);
+ abstract class
+     Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.Dy
+     namicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] T> :
+     Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ override ValueComparer CreateDefaultComparer(bool favorStructuralComparisons);
+ RelationalTypeMapping(RelationalTypeMappingParameters parameters);
+ RelationalTypeMapping(string storeType, Type clrType, DbType? dbType = null, bool unicode = false, int? size = null, bool fixedLength = false,
+     int? precision = null, int? scale = null, JsonValueReaderWriter? jsonValueReaderWriter = null);
- class Microsoft.EntityFrameworkCore.Storage.SByteTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.SByteTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<sbyte>
- class Microsoft.EntityFrameworkCore.Storage.ShortTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.ShortTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<short>
- class Microsoft.EntityFrameworkCore.Storage.StringTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.StringTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<string>
- class Microsoft.EntityFrameworkCore.Storage.TimeOnlyTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.TimeOnlyTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<System.TimeOnly>
- class Microsoft.EntityFrameworkCore.Storage.TimeSpanTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.TimeSpanTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<System.TimeSpan>
- class Microsoft.EntityFrameworkCore.Storage.UIntTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.UIntTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<uint>
- class Microsoft.EntityFrameworkCore.Storage.ULongTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.ULongTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<ulong>
- class Microsoft.EntityFrameworkCore.Storage.UShortTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping
+ class Microsoft.EntityFrameworkCore.Storage.UShortTypeMapping : Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping<ushort>

API review baseline changes for src/EFCore/EFCore.baseline.json

Show diff

The diff below was generated by ApiChief between the base and the PR.

  class
      Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.Dyn
      amicallyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] T> :
      Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer, System.Collections.Generic.IEqualityComparer<T>
+ static ValueComparer<T> Default { get; }
+ static ValueComparer<T> DefaultWithStructuralComparisons { get; }
  abstract class Microsoft.EntityFrameworkCore.Storage.CoreTypeMapping
- virtual CoreTypeMapping Clone(in TypeMappingInfo? mappingInfo = null, Type? clrType = null, ValueConverter? converter = null, ValueComparer? comparer = null,
-     ValueComparer? keyComparer = null, ValueComparer? providerValueComparer = null, CoreTypeMapping? elementMapping = null,
-     JsonValueReaderWriter? jsonValueReaderWriter = null);
+ virtual CoreTypeMapping Clone(in TypeMappingInfo? mappingInfo = null, ValueConverter? converter = null, ValueComparer? comparer = null,
+     ValueComparer? keyComparer = null, ValueComparer? providerValueComparer = null, CoreTypeMapping? elementMapping = null,
+     JsonValueReaderWriter? jsonValueReaderWriter = null);
+ virtual ValueComparer CreateDefaultComparer(bool favorStructuralComparisons);
+ abstract class
+     Microsoft.EntityFrameworkCore.Storage.CoreTypeMapping<[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.Dynamica
+     llyAccessedMemberTypes.PublicMethods | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicProperties)] T> :
+     Microsoft.EntityFrameworkCore.Storage.CoreTypeMapping
+ CoreTypeMapping(CoreTypeMappingParameters parameters);
+ override ValueComparer CreateDefaultComparer(bool favorStructuralComparisons);
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.BoolToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.BoolToTwoValuesConverter<string>
+ static BoolToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.BoolToZeroOneConverter<TProvider> :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.BoolToTwoValuesConverter<TProvider>
+ static BoolToZeroOneConverter<TProvider> Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.BytesToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<byte[]?, string?>
+ static BytesToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.CastingConverter<TModel,
      TProvider> : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<TModel, TProvider>
+ static CastingConverter<TModel, TProvider> Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.CharToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringCharConverter<char, string>
+ static CharToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.DateOnlyToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringDateOnlyConverter<System.DateOnly, string>
+ static DateOnlyToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.DateTimeOffsetToBinaryConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.DateTimeOffset, long>
+ static DateTimeOffsetToBinaryConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.DateTimeOffsetToBytesConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.DateTimeOffset, byte[]>
+ static DateTimeOffsetToBytesConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.DateTimeOffsetToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringDateTimeOffsetConverter<System.DateTimeOffset, string>
+ static DateTimeOffsetToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.DateTimeToBinaryConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.DateTime, long>
+ static DateTimeToBinaryConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.DateTimeToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringDateTimeConverter<System.DateTime, string>
+ static DateTimeToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.EnumToNumberConverter<TEnum,
      TNumber> : Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<TEnum, TNumber> where TEnum : struct, System.Enum where TNumber : struct
+ static EnumToNumberConverter<TEnum, TNumber> Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.EnumToStringConverter<TEnum> :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringEnumConverter<TEnum, string, TEnum> where TEnum : struct, System.Enum
+ static EnumToStringConverter<TEnum> Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.GuidToBytesConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.Guid, byte[]>
+ static GuidToBytesConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.GuidToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringGuidConverter<System.Guid, string>
+ static GuidToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.IPAddressToBytesConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.Net.IPAddress?, byte[]?>
+ static IPAddressToBytesConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.IPAddressToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.Net.IPAddress?, string?>
+ static IPAddressToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.NumberToBytesConverter<TNumber> :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<TNumber, byte[]>
+ static NumberToBytesConverter<TNumber> Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.NumberToStringConverter<TNumber> :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringNumberConverter<TNumber, string, TNumber>
+ static NumberToStringConverter<TNumber> Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.PhysicalAddressToBytesConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.Net.NetworkInformation.PhysicalAddress?, byte[]?>
+ static PhysicalAddressToBytesConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.PhysicalAddressToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.Net.NetworkInformation.PhysicalAddress?, string?>
+ static PhysicalAddressToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToBoolConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<string, bool>
+ static StringToBoolConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToBytesConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<string?, byte[]?>
+ static StringToBytesConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToCharConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringCharConverter<string, char>
+ static StringToCharConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToDateTimeConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringDateTimeConverter<string, System.DateTime>
+ static StringToDateTimeConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToDateTimeOffsetConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringDateTimeOffsetConverter<string, System.DateTimeOffset>
+ static StringToDateTimeOffsetConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToEnumConverter<TEnum> :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringEnumConverter<string, TEnum, TEnum> where TEnum : struct, System.Enum
+ static StringToEnumConverter<TEnum> Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToGuidConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringGuidConverter<string, System.Guid>
+ static StringToGuidConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToNumberConverter<TNumber> :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringNumberConverter<string, TNumber, TNumber>
+ static StringToNumberConverter<TNumber> Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToTimeOnlyConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringTimeOnlyConverter<string, System.TimeOnly>
+ static StringToTimeOnlyConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToTimeSpanConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringTimeSpanConverter<string, System.TimeSpan>
+ static StringToTimeSpanConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.StringToUriConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringUriConverter<string?, System.Uri?>
+ static StringToUriConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.TimeOnlyToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringTimeOnlyConverter<System.TimeOnly, string>
+ static TimeOnlyToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.TimeOnlyToTicksConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.TimeOnly, long>
+ static TimeOnlyToTicksConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.TimeSpanToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringTimeSpanConverter<System.TimeSpan, string>
+ static TimeSpanToStringConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.TimeSpanToTicksConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.ValueConverter<System.TimeSpan, long>
+ static TimeSpanToTicksConverter Instance { get; }
  class Microsoft.EntityFrameworkCore.Storage.ValueConversion.UriToStringConverter :
      Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal.StringUriConverter<System.Uri?, string?>
+ static UriToStringConverter Instance { get; }

@lewing

lewing commented Jun 23, 2026

Copy link
Copy Markdown
Member

This PR introduced a new ValueConverter<TModel, TProvider>(Expression, Expression, bool) overload that causes a CS0121 ambiguous call in aspnetcore's IdentityUserContext.cs:145, which passes null as the third argument (now ambiguous between ConverterMappingHints? and bool).

This is blocking the efcore forward flow into dotnet/dotnet for 6 days: dotnet/dotnet#7266

Build failure example: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1476539

error CS0121: The call is ambiguous between the following methods or properties:
'ValueConverter<string, string>.ValueConverter(..., ConverterMappingHints?)'
and 'ValueConverter<string, string>.ValueConverter(..., bool)'

cc @dotnet/efteam @dotnet/aspnet-build -- one of the two repos needs a fix (either disambiguate the call site in aspnetcore, or adjust the overload shape in efcore).

@AndriySvyryd AndriySvyryd added api-review This PR or issue is introducing public API changes that need to be reviewed and removed api-review This PR or issue is introducing public API changes that need to be reviewed labels Jun 23, 2026
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 11.0-preview6 milestone Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compiled models generate non-aot compatible code (repro included)

4 participants