Skip to content

Throw for unions mapped as entity or complex types - #38398

Merged
AndriySvyryd merged 4 commits into
mainfrom
copilot/throw-for-unions
Jun 17, 2026
Merged

Throw for unions mapped as entity or complex types#38398
AndriySvyryd merged 4 commits into
mainfrom
copilot/throw-for-unions

Conversation

Copilot AI commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

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

  • Detection (SharedTypeExtensions): added Type.IsUnion(), which checks for System.Runtime.CompilerServices.UnionAttribute (matched by full name to avoid a compile-time dependency on the marker type).
  • Validation (ModelValidator): throw CoreStrings.UnionTypeNotSupported from ValidateEntityType (union entity types) and ValidatePropertyMapping(IComplexProperty) (union complex types; also covers complex collections and value-type unions).
  • Resource: new UnionTypeNotSupported string in CoreStrings.
  • Tests: ModelValidatorTest cases for union entity and complex types, simulated via the real [Union] attribute.

Message

The type '{type}' cannot be mapped because union types are not supported. See #36375 for more information.

Notes

  • Applies across all providers via the shared ModelValidator.
  • Detection keys off the canonical [Union] marker, so it covers both class and struct unions.

Copilot AI linked an issue Jun 10, 2026 that may be closed by this pull request
Copilot AI and others added 2 commits June 10, 2026 18:17
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
Copilot AI requested a review from AndriySvyryd June 10, 2026 18:23
@AndriySvyryd
AndriySvyryd requested a review from Copilot June 10, 2026 19:07

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 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 in SharedTypeExtensions (attribute full-name match to avoid hard dependency).
  • Throw CoreStrings.UnionTypeNotSupported(...) from ModelValidator when 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

Comment thread src/EFCore/Properties/CoreStrings.Designer.cs
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI requested a review from AndriySvyryd June 10, 2026 21:19
@AndriySvyryd
AndriySvyryd marked this pull request as ready for review June 10, 2026 22:05
@AndriySvyryd
AndriySvyryd requested a review from a team as a code owner June 10, 2026 22:05
Copilot AI review requested due to automatic review settings June 10, 2026 22:05
@AndriySvyryd
AndriySvyryd requested a review from cincuranet June 10, 2026 22:07

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 5 out of 6 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • src/EFCore/Properties/CoreStrings.Designer.cs: Language not supported

@AndriySvyryd
AndriySvyryd merged commit a18fcc4 into main Jun 17, 2026
15 checks passed
@AndriySvyryd
AndriySvyryd deleted the copilot/throw-for-unions branch June 17, 2026 02:52
@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 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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.

  static class Microsoft.EntityFrameworkCore.Diagnostics.CoreStrings
+ static string UnionTypeNotSupported(object? type);

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Throw for unions

4 participants