Reverse processing order of setters in precompiled ExecuteUpdate#37323
Reverse processing order of setters in precompiled ExecuteUpdate#37323roji merged 3 commits intodotnet:mainfrom
Conversation
Refactor processing of method call expressions in setters.
Remove incorrect double-addition of properties during tree traversal
|
@dotnet-policy-service agree |
|
@SerhiiKozachenko what's the problem this is solving exactly, and why is this needed? When submitting a PR, please include at least a minimal description of what it's for. |
|
@roji I have updated description with more info, please check. |
249ae47 to
6b86657
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes incorrect setter parameter ordering when generating precompiled-query interceptor code for ExecuteUpdate/ExecuteUpdateAsync chains, ensuring SetProperty calls are processed in the same order as written in source.
Changes:
- Collects nested
SetPropertyMethodCallExpressions into a stack during traversal. - Replays collected calls in reverse-traversal order so setters are added First → Last as in source code.
src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs
Outdated
Show resolved
Hide resolved
|
Thanks, the problem statement makes sense, but the implementation is quite over-complicated, with a stack and an additional loop. I've pushed a one-line commit to simply reverse the setters at the end instead, which is much simpler. |
Refactor processing of method call expressions in setters.
Problem it solves:
ExecuteUpdateAsyncwithSetPropertychain generates reversed parameters in AOT Interceptors, causing InvalidCastException.When running
dotnet ef dbcontext optimizewith--precompile-queriesand--nativeaot, the generated interceptor code for anExecuteUpdateAsyncchain appears to process theSetPropertycalls in reverse order (Last-In-First-Out) instead of source order.This results in a mismatch between the parameter expected by the generated SQL and the value supplied by the interceptor.
Steps to Reproduce:
ExecuteUpdateAsynccall with multipleSetPropertycalls of different types.dotnet ef dbcontext optimize --precompile-queries --nativeaot ...Expected Behavior: The interceptor should map
Expressions[0]to the first property (IsDeleted) andExpressions[1]to the second (LastModified), matching the source order.Actual Behavior: The generated code assumes
Expressions[0]corresponds to the last property written (LastModified/now), effectively reversing the parameters.Runtime Exception: Because
Expressions[0](Boolean) is being passed into the parameter expectingDateTime(TimestampTz), Npgsql throws a cast exception:Proposed Fix: The issue appears to be in
PrecompiledQueryCodeGenerator.ProcessExecuteUpdate. The method iterates over theMethodCallExpressiontree (which is nested inside-out) but does not reverse the order before building the setters array.Using a
Stack<MethodCallExpression>to collect and then reverse the calls fixes the issue by ensuring setters are added in source code order (First -> Last).