Skip ALTER COLUMN for computed columns when only CLR type changes#38252
Open
m-x-shokhzod wants to merge 1 commit into
Open
Skip ALTER COLUMN for computed columns when only CLR type changes#38252m-x-shokhzod wants to merge 1 commit into
m-x-shokhzod wants to merge 1 commit into
Conversation
Member
Have you verified whether this is a SQL Server-specific thing, or universal to all databases? I'm pretty sure it's the former, in which case you're introducing a SQL Server-specific change into ModelDiffer, which is provider-independent. |
The migration model differ produced an AlterColumnOperation when the CLR
type of a property mapped to a computed column changed (e.g. int → long
for a column with .HasComputedColumnSql("DATALENGTH(...)")). The
generated ALTER TABLE ... ALTER COLUMN then failed at runtime with
"Cannot alter column ... because it is 'COMPUTED'".
A computed column's store type and collation are derived from the
expression; they aren't user-configurable. CLR-type-only changes are
metadata on the EF side and require no database-side change. SQL Server
specifically rejects ALTER COLUMN on computed columns altogether.
The fix lives in SqlServerMigrationsSqlGenerator (provider-specific):
when both source and target are computed, set alterStatementNeeded to
false. This suppresses the ALTER COLUMN emission while letting other
separately-emitted facets (notably the comment block at line 488 via
sp_addextendedproperty) still apply. The drop+add path for expression
changes earlier in the method is unchanged.
MigrationsModelDiffer remains provider-independent: it still produces
AlterColumnOperation as before; other providers (MySQL with MODIFY
COLUMN, PostgreSQL, etc.) decide for themselves how to handle it.
Tests:
- Unit: AlterColumnOperation_computed_column_with_only_clr_type_change_is_noop
asserts the generator produces empty SQL for the bug case.
- Unit: AlterColumnOperation_computed_column_with_changed_expression_drops_and_adds
guards the existing drop+add path.
- Functional: Alter_computed_column_clr_type_only_change_is_noop runs the
scenario end-to-end against real SQL Server in the CI matrix; verified
locally against Azure SQL Edge on Apple Silicon.
Fixes dotnet#33425
ad662f8 to
cdc292a
Compare
Contributor
Author
|
Good point — you're right. The constraint is SQL Server specific: PostgreSQL and SQLite have similar but narrower restrictions on generated columns, and MySQL handles type changes on generated columns fine via Reworked (force-pushed
|
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.
The migration model differ produced an
AlterColumnOperationwhen the CLR type of a property mapped to a computed column changed (e.g.int→longfor a column with.HasComputedColumnSql("DATALENGTH(...)")). The resultingALTER TABLE ... ALTER COLUMNthen failed at runtime with:A computed column's store type and collation are derived from the expression; they aren't user-configurable. CLR-type-only changes are metadata on the EF side and require no database-side change.
Fix
In
MigrationsModelDiffer.Diff(IColumn, IColumn, DiffContext), suppresscolumnTypeChangedandcollationChangedwhen both source and target are computed with the sameComputedColumnSqlandIsStored:Behavior
int→long), same expressionAlterColumnOperation→ALTER COLUMN→ SQL Server rejectsDATALENGTH→LEN)AlterColumnOperation→ SQL generator's drop+add pathAlterColumnOperation→ALTER COLUMNAlterColumnOperationproducedTests
Computed_column_clr_type_change_alone_is_no_op— bug case from Migration tries to alter column type of computed column if CLR type changes. #33425; reproduces exactly withDATALENGTH([FileContents])and asserts zero operationsComputed_column_expression_change_with_clr_type_change_still_alters— guards the existing drop+add pathFull Relational.Tests suite passes (1427/1428, the 1 skip is pre-existing). SqlServer.Tests suite passes (1335/1335). End-to-end coverage will run on the SqlServer 2019/2022/2025 CI matrix.
Fixes #33425