Skip to content

Allow changing CLR type without SQL conversion - #39397

Merged
AndriySvyryd merged 5 commits into
dotnet:mainfrom
z0rimo:feature/33733-clr-type-change-expression
Nov 13, 2026
Merged

AndriySvyryd merged 5 commits into
dotnet:mainfrom
z0rimo:feature/33733-clr-type-change-expression

Conversation

@z0rimo

@z0rimo z0rimo commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #33733

This adds a dedicated ClrTypeChangeExpression which allows a SQL expression to expose a different CLR type without emitting a corresponding SQL conversion.

  • Add a CLR type change SQL expression which is omitted during SQL generation.
  • Integrate the expression with type mapping, nullability processing, SQL generation, and parentheses handling.
  • Use it for enums configured with EnumToStringConverter<>, avoiding unnecessary SQL CASTs for ToString().
  • Extend the existing string-converted enum regression coverage with a composed ToString().Contains(...) case.

Local validation:

  • ./build.sh
  • EFCore.ApiBaseline.Tests: 14 passed
  • EFCore.Relational.Tests: 1,525 passed, 1 skipped
  • EFCore.Sqlite.FunctionalTests: 38,334 passed, 285 skipped
  • Focused string-converted enum tests passed

SQL Server functional tests were not executed locally because the project skips tests on non-Windows environments when Test__SqlServer__DefaultConnection is not configured. The SQL Server test project and updated SQL baselines build successfully.

  • I've read the guidelines for contributing and seen the walkthrough(https://youtu.be/9OMxy1wal1s?t=1869)
  • I've posted a comment on an issue with a detailed description of how I am planning to contribute and got approval from a member of the team
  • The code builds and tests pass locally (also verified by our automated build checks)
  • Commit messages follow this format:
        Summary of the changes
        - Detail 1
        - Detail 2

        Fixes #bugnumber
  • Tests for the changes have been added (for bug fixes / features)
  • Code follows the same patterns and style as existing code in this repo

- Add a CLR type change SQL expression
- Use it for string-converted enum ToString()

Fixes dotnet#33733

Copilot AI left a comment

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.

🟡 Changes recommended

Removing casts exposes SQL Server store-type mismatches and truncation regressions in composed string operations.

2 open issues
What changed in this PR

Adds a SQL expression that changes the exposed CLR type without emitting a SQL conversion, addressing #33733 for string-converted enums.

Changes:

  • Introduces ClrTypeChangeExpression and integrates mapping, nullability, SQL generation, and parentheses handling.
  • Uses the new expression for enum ToString() translation.
  • Updates API baselines and adds composed ToString().Contains(...) coverage.
File Description
test/​EFCore.SqlServer.FunctionalTests/​Query/​AdHocMiscellaneousQuerySqlServerTest.cs Updates SQL Server baselines and adds the composed query baseline.
test/​EFCore.Sqlite.FunctionalTests/​Query/​AdHocMiscellaneousQuerySqliteTest.cs Updates SQLite baselines and adds the composed query baseline.
test/​EFCore.Relational.Specification.Tests/​Query/​AdHocMiscellaneousQueryRelationalTestBase.cs Adds shared result assertions for composed string operations.
src/​EFCore.Relational/​Query/​SqlNullabilityProcessor.cs Propagates operand nullability through the new expression.
src/​EFCore.Relational/​Query/​SqlExpressions/​ClrTypeChangeExpression.cs Defines the CLR-only type-change expression.
src/​EFCore.Relational/​Query/​SqlExpressionFactory.cs Supports mapping the new expression.
src/​EFCore.Relational/​Query/​QuerySqlGenerator.cs Emits only the operand and handles parentheses.
src/​EFCore.Relational/​Query/​Internal/​Translators/​EnumMethodTranslator.cs Replaces string-converted enum casts with the new expression.
src/​EFCore.Relational/​EFCore.Relational.baseline.json Records the added public and protected APIs.

Review effort: Balanced

@z0rimo
z0rimo marked this pull request as draft October 28, 2026 01:03
- Preserve converted enum store type mappings
- Widen bounded Replace inputs when required
- Add SQL Server regression coverage
@z0rimo
z0rimo marked this pull request as ready for review October 28, 2026 01:18
@AndriySvyryd
AndriySvyryd requested a lite review from Copilot October 28, 2026 22:12

Copilot AI left a comment

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.

🟡 Changes recommended

The PR bundles an unrelated SQL Server REPLACE translation change, which widens bounded varchar inputs to varchar(max) and affects plain string columns, but the PR description covers only the enum CLR type change and the related tests are not yet explained or split out.

1 open issue
2 resolved since last review

Review effort: Lite

@z0rimo
z0rimo marked this pull request as draft October 30, 2026 12:55
- Revert the EnumMethodTranslator and SqlServerStringMethodTranslator workarounds
- Wrap stripped no-op CASTs in ClrTypeChangeExpression when the CLR type or mapping changes
- Look through ClrTypeChangeExpression when deciding whether a projection alias is redundant
- Rework SQL Server regression coverage for bounded string-converted enums
@z0rimo
z0rimo force-pushed the feature/33733-clr-type-change-expression branch from eb05099 to 338fbbe Compare November 1, 2026 15:23
@z0rimo
z0rimo marked this pull request as ready for review November 1, 2026 15:36
@z0rimo
z0rimo marked this pull request as draft November 2, 2026 07:24
@z0rimo
z0rimo marked this pull request as ready for review November 2, 2026 07:49

Copilot AI left a comment

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.

🔵 Needs a closer look

Human verification is warranted because the change introduces a public SQL-expression node and cross-provider SQL generation changes that could affect SQL Server CAST behavior and downstream visitors, while SQL Server execution was unavailable locally.

No open issues 🎉

1 resolved since last review

Review effort: Lite

@z0rimo
z0rimo requested a review from AndriySvyryd November 3, 2026 02:02
@z0rimo
z0rimo marked this pull request as draft November 13, 2026 10:26
@z0rimo
z0rimo marked this pull request as ready for review November 13, 2026 10:26

@AndriySvyryd AndriySvyryd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for your contribution!

@AndriySvyryd
AndriySvyryd merged commit 40c6a06 into dotnet:main Nov 13, 2026
21 of 22 checks passed
@github-actions github-actions Bot added the api-review This PR or issue is introducing public API changes that need to be reviewed label Nov 13, 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.Query.QuerySqlGenerator : System.Linq.Expressions.ExpressionVisitor
+ virtual Expression VisitClrTypeChange(ClrTypeChangeExpression clrTypeChangeExpression);
+ class Microsoft.EntityFrameworkCore.Query.SqlExpressions.ClrTypeChangeExpression : Microsoft.EntityFrameworkCore.Query.SqlExpressions.SqlExpression
+ virtual SqlExpression Operand { get; }
+ virtual ClrTypeChangeExpression ApplyTypeMapping(RelationalTypeMapping? typeMapping);
+ ClrTypeChangeExpression(SqlExpression operand, Type type, RelationalTypeMapping? typeMapping);
+ virtual ClrTypeChangeExpression Update(SqlExpression operand);
  class Microsoft.EntityFrameworkCore.Query.SqlNullabilityProcessor : System.Linq.Expressions.ExpressionVisitor
+ virtual SqlExpression VisitClrTypeChange(ClrTypeChangeExpression clrTypeChangeExpression, bool allowOptimizedExpansion, out bool nullable);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-review This PR or issue is introducing public API changes that need to be reviewed community-contribution

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow changing CLR type in query translation without additional SQL

3 participants