[release/10.0] Fix invalid SQL parameter names for switch/case pattern-matched variables#37805
[release/10.0] Fix invalid SQL parameter names for switch/case pattern-matched variables#37805Copilot wants to merge 4 commits intorelease/10.0from
Conversation
…se pattern-matched variables Co-authored-by: roji <1862641+roji@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR backports a fix for #37465, which addresses a critical regression in EF Core 10.0.1 where switch/case pattern-matched variables generate invalid SQL parameter names starting with digits (e.g., @5__2_Task). The C# compiler generates closure field names with angle brackets for pattern-matched variables (e.g., <customerId>5__2), and EF Core's previous logic was stripping everything after the last >, leaving invalid names. The fix introduces a SanitizeCompilerGeneratedName helper that extracts the user-provided variable name from within the angle brackets and adds a safety net to prepend _ if needed.
Changes:
- Introduce
SanitizeCompilerGeneratedNamehelper method that correctly parses compiler-generated field names to extract user-provided variable names - Add AppContext switch
UseOldBehavior37465for backward compatibility - Add safety net to prepend underscore for parameter names starting with invalid characters
- Add test case
Captured_variable_from_switch_case_pattern_matchingto verify fix
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs | Core fix: adds SanitizeCompilerGeneratedName helper, quirk mode switch, and applies sanitization at field/property/method name extraction points |
| test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs | Adds base test reproducing the switch/case pattern-matching scenario from issue #37465 |
| test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs | SQL Server override with assertion that parameter name is @customerId (not @5__2_Task) |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
artl93
left a comment
There was a problem hiding this comment.
Approved. Regression, customer reported, important scenario.
Fixes #37465
Backports #37474
Description
When using a C# switch/case pattern-matched variable in a LINQ query (e.g., case string customerId:), EF Core 10 generates an invalid SQL parameter name starting with a digit (e.g., @5__2_Task). This is because the C# compiler generates closure field names with angle brackets (e.g., <>5__2) for pattern-matched variables, and EF Core's ExpressionTreeFuncletizer was stripping everything up to and including the last >, leaving a name that starts with a digit. The fix introduces a SanitizeCompilerGeneratedName helper that correctly extracts the user-provided variable name from within the angle brackets (e.g., extracting customerId from 5__2), and adds a safety net to prepend _ if the resulting name still starts with an invalid character.
Customer impact
Any EF Core 10 application using switch/case pattern matching to capture variables in LINQ queries will fail at runtime if the database does not accept parameter names starting with non-alphabetic characters. This is particularly critical for Azure Cosmos DB, which validates parameter names and throws a BadRequest error. SQL Server and SQLite accept these names silently but the parameter names are still incorrect/confusing. There is no simple workaround other than copying the value to a separate non-pattern-matched local variable.
How found
Customer-reported issue on GitHub. Multiple customers have been affected (confirmed by reactions on the issue).
Regression
Yes, this is a regression introduced in EF Core 10.0.1. In EF 8 and EF 9, the generated parameter names were valid (e.g., @__5__2_Task_0). The regression was introduced in EF 10 when the parameter naming logic in ExpressionTreeFuncletizer was refactored.
Testing
Added a new test Captured_variable_from_switch_case_pattern_matching to NorthwindMiscellaneousQueryTestBase that directly reproduces the reported scenario. Added SQL Server and Cosmos overrides with expected SQL/query output. The test verifies that a pattern-matched variable in a switch/case statement generates a valid parameter name (e.g., @customerId) and the query executes successfully.
Risk
Low. The fix is surgical: it only changes how compiler-generated names with angle brackets are sanitized, which only affects pattern-matched switch/case variables and certain other compiler-generated closures. A UseOldBehavior37465 AppContext switch is provided to revert to the previous behavior if needed. The change has no impact on queries that don't use pattern-matched variables.