Throw for unions mapped as entity or complex types - #38398
Merged
Conversation
Closed
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Throw error for unions as entity types in EF
Throw for unions mapped as entity or complex types
Jun 10, 2026
There was a problem hiding this comment.
Pull request overview
This PR adds first-class model validation for upcoming C# union types by detecting [System.Runtime.CompilerServices.Union] / UnionAttribute on CLR types and throwing a clear, user-facing error when such types are mapped as EF entity or complex types (aligning behavior across all providers).
Changes:
- Add
Type.IsUnion()detection inSharedTypeExtensions(attribute full-name match to avoid hard dependency). - Throw
CoreStrings.UnionTypeNotSupported(...)fromModelValidatorwhen unions are encountered as entity or complex types. - Add the new resource string and unit tests covering both entity-type and complex-type mapping scenarios.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs | Adds regression tests asserting unions mapped as entity/complex types produce the new clear validation error. |
| src/Shared/SharedTypeExtensions.cs | Introduces IsUnion() extension method based on UnionAttribute full-name detection. |
| src/EFCore/Infrastructure/ModelValidator.cs | Enforces the new validation rule by throwing UnionTypeNotSupported for union entity/complex types. |
| src/EFCore/Properties/CoreStrings.resx | Adds the user-facing error message resource for unsupported union mapping. |
| src/EFCore/Properties/CoreStrings.Designer.cs | Adds the generated accessor for UnionTypeNotSupported. |
Files not reviewed (1)
- src/EFCore/Properties/CoreStrings.Designer.cs: Language not supported
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
cincuranet
approved these changes
Jun 16, 2026
Contributor
API review baseline changes for
|
wtgodbe
pushed a commit
that referenced
this pull request
Jul 28, 2026
The C# preview "union" language feature now compiles union declarations (e.g. union UnionEntity(int);) as value types (structs implementing System.Runtime.CompilerServices.IUnion), rather than reference types. This broke the existing detection of union types mapped as entity or complex types added in #38398: - SharedTypeExtensions.IsValidEntityType required IsClass: true, so EntityType's constructor now threw a generic ArgumentException ("must be a non-interface reference type") as soon as a union type was added to the model, before ModelValidator ever got a chance to detect it and produce the specific UnionTypeNotSupported message. - ConstructorBindingConvention (an IModelFinalizingConvention that runs during FinalizeModel, before ModelValidator.Validate) attempted to bind a constructor for union types used as complex properties, throwing "No suitable constructor was found" before the model validator's union check was reached. Fix: - IsValidEntityType now also accepts union types (mirroring IsValidComplexType, which already allowed them), so union entity types can still be added to the model and are rejected later, with the intended friendly error message, by ModelValidator. - ConstructorBindingConvention now skips constructor binding for union entity/complex types, since they can never have a meaningful constructor binding, allowing model finalization to proceed to ModelValidator.Validate where the specific union error is thrown. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
wtgodbe
added a commit
that referenced
this pull request
Jul 29, 2026
* Backflow from https://github.com/dotnet/dotnet / 7bcb900 build 324583 Diff: https://github.com/dotnet/dotnet/compare/dadfb24164945e42d8fda33324ddf87b99b7686d..7bcb9009c40399c9073e7db938250486229cc85d From: dotnet/dotnet@dadfb24 To: dotnet/dotnet@7bcb900 [[ commit created by automation ]] * Update dependencies from build 324583 Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 11.0.0-beta.26365.101 -> 11.0.0-beta.26376.106) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, Microsoft.NETCore.Platforms, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 11.0.0-preview.7.26365.101 -> 11.0.0-preview.7.26376.106) [[ commit created by automation ]] * Fix union model validator tests for new union shape Co-authored-by: wtgodbe <14283640+wtgodbe@users.noreply.github.com> * Update union model validator tests for .NET 11 preview behavior Co-authored-by: wtgodbe <14283640+wtgodbe@users.noreply.github.com> * Update dependencies from build 324662 Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 11.0.0-beta.26376.106 -> 11.0.0-beta.26377.110) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, Microsoft.NETCore.Platforms, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 11.0.0-preview.7.26376.106 -> 11.0.0-preview.7.26377.110) [[ commit created by automation ]] * Update dependencies from build 324774 Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 11.0.0-beta.26377.110 -> 11.0.0-beta.26378.106) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, Microsoft.NETCore.Platforms, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 11.0.0-preview.7.26377.110 -> 11.0.0-preview.7.26378.106) [[ commit created by automation ]] * Revert "Update union model validator tests for .NET 11 preview behavior" This reverts commit 22b6fc6. * Revert "Fix union model validator tests for new union shape" This reverts commit 26b6058. * Fix union type detection after C# union types became value types The C# preview "union" language feature now compiles union declarations (e.g. union UnionEntity(int);) as value types (structs implementing System.Runtime.CompilerServices.IUnion), rather than reference types. This broke the existing detection of union types mapped as entity or complex types added in #38398: - SharedTypeExtensions.IsValidEntityType required IsClass: true, so EntityType's constructor now threw a generic ArgumentException ("must be a non-interface reference type") as soon as a union type was added to the model, before ModelValidator ever got a chance to detect it and produce the specific UnionTypeNotSupported message. - ConstructorBindingConvention (an IModelFinalizingConvention that runs during FinalizeModel, before ModelValidator.Validate) attempted to bind a constructor for union types used as complex properties, throwing "No suitable constructor was found" before the model validator's union check was reached. Fix: - IsValidEntityType now also accepts union types (mirroring IsValidComplexType, which already allowed them), so union entity types can still be added to the model and are rejected later, with the intended friendly error message, by ModelValidator. - ConstructorBindingConvention now skips constructor binding for union entity/complex types, since they can never have a meaningful constructor binding, allowing model finalization to proceed to ModelValidator.Validate where the specific union error is thrown. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: wtgodbe <14283640+wtgodbe@users.noreply.github.com> Co-authored-by: Will Godbe <willgodbe@Wills-MacBook-Pro.local> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #38376
EF doesn't support C# union types yet. Mapping one as an entity type or complex type currently produces undefined/confusing behavior instead of a clear error.
Changes
SharedTypeExtensions): addedType.IsUnion(), which checks forSystem.Runtime.CompilerServices.UnionAttribute(matched by full name to avoid a compile-time dependency on the marker type).ModelValidator): throwCoreStrings.UnionTypeNotSupportedfromValidateEntityType(union entity types) andValidatePropertyMapping(IComplexProperty)(union complex types; also covers complex collections and value-type unions).UnionTypeNotSupportedstring inCoreStrings.ModelValidatorTestcases for union entity and complex types, simulated via the real[Union]attribute.Message
Notes
ModelValidator.[Union]marker, so it covers bothclassandstructunions.