Fix in-memory corruption of nested owned entities after SaveChanges when navigation is replaced#37787
Draft
Fix in-memory corruption of nested owned entities after SaveChanges when navigation is replaced#37787
Conversation
…ith record with expression When an owned entity stored as JSON is replaced with a new instance that shares nested owned entity references (e.g., via C# record 'with' expression), the change tracker now properly handles the shared child entities: 1. EntityGraphAttacher.PaintAction: Allow entities in Deleted state to be re-attached when encountered during graph traversal of a new parent entity. 2. StateManager.CascadeDelete: Skip cascade deletion for dependents whose current principal (from identity map) has been replaced by a new entity via shared identity. Fixes #36017 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix in-memory corruption of nested owned entities after SaveChanges
Fix in-memory corruption of nested owned entities after SaveChanges when navigation is replaced
Feb 24, 2026
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.
When a JSON-mapped owned entity navigation is replaced with a new instance sharing nested child references (e.g., via C# record
withexpression), nested owned entities becomenullin memory afterSaveChanges, despite being correctly persisted to the database.Root cause: Three-step failure during the replace-and-save cycle:
DeletedEntityGraphAttacher.PaintActiononly processesDetachedentities, so shared children stuck inDeletedstate are skipped during attachment of the new parent graphCascadeDeleteinGetEntriesToSavere-cascades the old parent's deletion to the shared child, and duringAcceptChanges,DeleteFixupresolves the replacement principal via identity map and nulls its navigationChanges:
EntityGraphAttacher.PaintAction/PaintActionAsync: Process entities inDeletedstate (not justDetached) during graph traversal, allowing shared child entities to be re-attached to the new parentStateManager.CascadeDelete: Skip cascade whenFindPrincipalreturns a different entry than the one being cascaded from — this means the dependent has been re-associated with a replacement principal via shared identityJsonUpdateTestBase: AddReplace_json_reference_root_preserves_nested_owned_entities_in_memorycovering the replace-with-shared-children scenarioOriginal prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.