-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Allow SQL Server JSON mapping to non-max nvarchar #37425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
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 enables SQL Server JSON mapping to non-max nvarchar columns by updating the type mapping logic to match on the base type name rather than the full type name with size specification. This allows users to map JSON data to columns like nvarchar(2000) instead of only nvarchar(max).
Key Changes
- Modified the type mapping source to use
StoreTypeNameBaseinstead ofstoreTypeNamewhen determining JSON type mappings - Changed the pattern match from exact
"nvarchar(max)"to base type"nvarchar", which matches any nvarchar variant - Added test coverage for both structural JSON types and primitive collections with non-max nvarchar sizes
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/EFCore.SqlServer/Storage/Internal/SqlServerTypeMappingSource.cs | Updated JSON type mapping logic to match on base type name ("nvarchar") instead of full type name ("nvarchar(max)"), enabling flexible column sizing |
| test/EFCore.SqlServer.Tests/Storage/SqlServerTypeMappingSourceTest.cs | Added test Json_can_be_mapped_to_nvarchar_non_max() to verify JSON can be mapped to nvarchar with explicit size constraints |
The implementation is correct and follows the established pattern in the codebase. The WithTypeMappingInfo method properly applies the actual size from the mapping info to the returned type mapping, ensuring that nvarchar(2000) is preserved as the store type rather than being replaced with nvarchar(max).
| { | ||
| "json" => SqlServerStructuralJsonTypeMapping.JsonTypeDefault, | ||
| "nvarchar(max)" => SqlServerStructuralJsonTypeMapping.NvarcharMaxDefault, | ||
| "nvarchar" => SqlServerStructuralJsonTypeMapping.NvarcharMaxDefault, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it's not nvarchar(max) you'd need to create a new mapping with the specified length as it's done for strings below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AndriySvyryd on a deeper look...
First, the current behavior seems to be the same thing we had in 9.0, i.e. return an nvarchar(max) mapping that then gets cloned with the correct length facet (so the returned store type is indeed nvarchar(2000), not max).
Second, IIUC, if the user explicitly specifies a store type, for strings as well we don't go through the creation of a new string type mapping via the code you're referring to; we find nvarchar(max) or nvarchar (the base store type) in _storeTypeMappings, and then just return that (that gets cloned with the right size outside of SqlServerTypeMappingSource).
The "complicated" fragment which constructs new SqlStringStringTypeMappings kicks in only when there's no store type configured, and allows users to optionally specify the size via data annotations/fluent API. But I don't think we allow MaxLength to be configured on complex properties (they're not regular properties). In other words, if users want a non-max nvarchar, they have to currently specify the store type fully and directly, rather than rely on size data annotation/fluent API.
So I think the current thing is in line with what we're already doing for strings, but this is a tricky area, so definitely take a look and let me know what you think.
There was a problem hiding this comment.
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 2 out of 2 changed files in this pull request and generated no new comments.
Fixes #37424