[release/10.0] Fix SetProperty discard lambda failing for nullable value type properties in ExecuteUpdate#38007
Open
roji wants to merge 1 commit intodotnet:release/10.0from
Open
[release/10.0] Fix SetProperty discard lambda failing for nullable value type properties in ExecuteUpdate#38007roji wants to merge 1 commit intodotnet:release/10.0from
roji wants to merge 1 commit intodotnet:release/10.0from
Conversation
…ties in ExecuteUpdate Backport of dotnet#37975 to release/10.0. In ExpressionTreeFuncletizer.ProcessEvaluatableRoot, ConvertIfNeeded calls Visit which corrupts _state back to EvaluatableWithoutCapturedVariable when wrapping a constant int to int?. This causes the parent VisitLambda to treat the lambda as evaluatable, compiling it to a Func and breaking TranslateSetterValueSelector. Fix: reset state to NoEvaluatability after ConvertIfNeeded returns. Added quirk Microsoft.EntityFrameworkCore.Issue37974 to opt out. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes an EF Core 10 regression where ExecuteUpdate/SetProperty using a discard lambda (_ => 1) fails when assigning a constant/literal to a nullable value type property (e.g. int?), by preventing ExpressionTreeFuncletizer state corruption during constantization and adding coverage for the scenario.
Changes:
- Reset funcletizer state after
ConvertIfNeededwhen constantizing an evaluatable root (with an AppContext quirk to opt out). - Add a new bulk update test covering
SetProperty(..., _ => 1)for a nullableintproperty in the Northwind spec tests. - Add SQLite and SQL Server SQL baseline assertions for the new test.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs | Resets state after ConvertIfNeeded to avoid _state corruption when constantizing, gated by an AppContext switch. |
| test/EFCore.Specification.Tests/BulkUpdates/NorthwindBulkUpdatesTestBase.cs | Adds provider-agnostic test for updating Product.SupplierID (int?) via discard-lambda constant setter. |
| test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesSqliteTest.cs | Adds SQLite SQL baseline for the new nullable-int discard-lambda update test. |
| test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesSqlServerTest.cs | Adds SQL Server SQL baseline for the new nullable-int discard-lambda update test. |
AndriySvyryd
approved these changes
Mar 26, 2026
artl93
approved these changes
Mar 27, 2026
Member
artl93
left a comment
There was a problem hiding this comment.
Approved. Regression. Customer reported.
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.
Fixes #37974
Backports #37975
Description
When using
ExecuteUpdatewithSetPropertyto assign a constant or literal value to a nullable value type property (e.g.int?) via a discard lambda (_ => 1), EF Core throwsInvalidOperationException: No coercion operator is defined between types Func<Entity, int?> and int. This was introduced by the EF Core 10 refactoring ofExecuteUpdatefromExpression<Func<...>>toFunc<...>for the setter parameter.The root cause is in
ExpressionTreeFuncletizer.ProcessEvaluatableRoot: when constantizing a value that needs a nullable conversion (e.g.int→int?),ConvertIfNeededinternally callsVisit, which corrupts the_statefield back toEvaluatableWithoutCapturedVariable. This causes the parentVisitLambdato incorrectly treat the entire lambda as evaluatable, compiling it into aFunc<Entity, int?>delegate. The downstreamTranslateSetterValueSelectorthen receives aQueryParameterExpressioninstead of aLambdaExpressionand throws.Customer impact
Users calling
ExecuteUpdateAsyncwith a constant/literal value assigned to a nullable value type property via a discard lambda get anInvalidOperationExceptionat query compilation time. This is a common pattern:Workarounds exist: cast the value to
int?explicitly, or use a named parameter (p =>) instead of a discard (_ =>). Both workarounds are somewhat discoverable from the error message but unintuitive.How found
User reported on EF Core 10.0.0. One additional user has also reported being affected. The issue has 2 reactions (+1 and eyes).
Regression
Yes, this is a regression from EF Core 9 to EF Core 10. It was introduced as a side effect of the
ExecuteUpdaterefactoring that changed the setter parameter fromExpression<Func<...>>toFunc<...>(the breaking change documented at https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-10.0/breaking-changes#execute-update-expression).Testing
Added 1 new test (
Update_Where_set_nullable_int_constant_via_discard_lambda) with SQL baseline assertions in both SQLite and SQL Server test classes.Risk
Extremely low. The fix is a single-line state reset (
state = State.NoEvaluatability) afterConvertIfNeededreturns, restoring the state that was already set earlier in the method but got corrupted by the internalVisitcall. Quirk added (Microsoft.EntityFrameworkCore.Issue37974) to opt out.