Fix .Update() marking AfterSaveBehavior.Throw properties as modified via DetectChanges#38115
Merged
AndriySvyryd merged 6 commits intomainfrom Apr 16, 2026
Merged
Conversation
…s during Update() to prevent DetectChanges from re-marking them as modified In SetEntityState with modifyProperties=true, after unflagging Throw properties, also ensure their original values match current values. This prevents DetectChanges from finding false mismatches due to snapshot factories storing default values for shadow properties on complex types. Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/226e05b5-79be-4c42-9c60-b85c45bcf703 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/226e05b5-79be-4c42-9c60-b85c45bcf703 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot created this pull request from a session on behalf of
AndriySvyryd
April 15, 2026 21:00
View session
Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/25d6f7dd-9b21-494f-af74-0354cf40a642 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a regression where DbContext.Update() combined with DetectChanges can re-mark AfterSaveBehavior.Throw properties (notably the complex-type discriminator shadow property) as modified, causing SaveChanges to throw for optional complex types.
Changes:
- Update
InternalEntryBase.SetEntityStateto synchronize original values forAfterSaveBehavior.Throwproperties with current values to prevent false mismatches duringDetectChanges. - Add a regression test covering
Update()on an entity with a nullable complex type discriminator to ensureSaveChangesAsyncsucceeds.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/EFCore/ChangeTracking/Internal/InternalEntryBase.cs | Adjusts state-setting logic to prevent DetectChanges from re-marking Throw properties as modified due to snapshot/current mismatches. |
| test/EFCore.Specification.Tests/Query/AdHocComplexTypeQueryTestBase.cs | Adds a regression test validating Update() + optional complex type discriminator no longer throws on save. |
…move second pass Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/920653c7-9690-47d4-8d9d-10857f722725 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
…lex_type_and_discriminator_does_not_throw Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/c4bbf4d0-14d6-4657-8eff-040197cda3bb Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
…Sql with actual SQL Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/35584ae8-0472-4f4c-9a93-cdd770e3d1a3 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
roji
approved these changes
Apr 16, 2026
Member
roji
left a comment
There was a problem hiding this comment.
@AndriySvyryd is this something we need to service?
Member
I think it's a corner case as we only had one report since 10.0.3 |
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 #38105
DbContext.Update()on an entity with a nullable complex type + discriminator throws duringSaveChanges:Regression from #37394: the snapshot factory stores default values for shadow properties on complex types, so
DetectChangesfinds a false mismatch between the current discriminator value (set by value generator) and the snapshot (null), re-marking theThrowproperty as modified afterSetEntityStatecorrectly unflagged it.Changes
InternalEntryBase.SetEntityState: In themodifyPropertiesblock, after unflaggingThrowproperties, set their original values to match current values (guarded by!IsConceptualNull(property)) inline in the same loop soDetectChangeswon't find a false mismatch and re-mark them as modified.Test: Added
Update_entity_with_nullable_complex_type_and_discriminator_does_not_throw— inserts entity with nullable complex type + discriminator, clears tracker, callsUpdate()with a new disconnected instance, assertsSaveChangesAsyncsucceeds.A more targeted fix is proposed in #38111, but I believe this is a more robust approach