Repository navigation
Preserve owned replacements during tracking queries - #39663
AndriySvyryd wants to merge 2 commits into
Conversation
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
| if (entry is { EntityState: EntityState.Added }) | ||
| // must be corrected to Unchanged unless it replaces a deleted entry. Otherwise it would be re-inserted, | ||
| // causing a duplicate key. See #35762. | ||
| if (entry is { EntityState: EntityState.Added, SharedIdentityEntry: not { EntityState: EntityState.Deleted } }) |
There was a problem hiding this comment.
@copilot Update progress by rewriting the PR summary using this template:
Fixes #{number}
**Description**
{Issue description}
**Customer impact**
{How does the reported issue affects customer's app? Are there workarounds?}
**How found**
{Was it customer reported or found during verification? How many customers are affected?}
**Regression**
{Is it a regression from a released version? Which one?}
**Testing**
{How the changes were tested}
**Risk**
{Low/Medium/High, argument why}
There was a problem hiding this comment.
The available tools cannot directly edit the PR description, and browser access was blocked. Here is the replacement summary for the changes in 686dc3e:
Fixes #39595
Description
A tracking query returning an owner can incorrectly mark a replacement owned reference as Unchanged, discarding its pending update. Preserve the replacement's Added state when it shares its identity with a deleted original.
Customer impact
Changes to replaced owned references are silently lost when the owner is returned by a tracking query before SaveChanges. Reported with JSON and table-splitting mappings on SQLite and Npgsql. A workaround is to save the replacement before executing another tracking query.
How found
Customer reported on EF Core 11.0.0 and 11.0.0-rc.3.26522.148. One customer report is documented; the total number affected is unknown.
Regression
Regression from EF Core 10.0.14, where the reported scenario works. Introduced by #38452's normalization of matching Added entries during tracking queries.
Testing
Added one parameterized regression test covering JSON and table splitting. Both cases reproduced the failure before the fix. After the fix, all 24 targeted SQLite update tests and the existing Added-entry normalization test passed (25 tests total).
Risk
Low. The fix adds a single condition to the existing state transition, preserving ordinary Added-entry normalization. Regression tests verify pending states and persisted values for both affected mappings.
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues are identified, and the change includes targeted regression coverage for preserving replacement states and persisted values across the affected mappings.
No open issues 🎉
What changed in this PR
Preserves pending owned-entity replacements during tracking queries so replacements of deleted shared-identity entries remain Added and are persisted correctly by SaveChanges.
Changes:
- Skips Added-to-Unchanged normalization for replacements of deleted shared-identity entries.
- Adds SQLite regression coverage for table-splitting and JSON-owned mappings, including state and persisted-value assertions.
| File | Description |
|---|---|
| test/EFCore.Sqlite.FunctionalTests/Update/NonSharedModelUpdatesSqliteTest.cs | Adds regression tests verifying owned replacement states and persisted values for table-splitting and JSON mappings. |
| src/EFCore/Query/QueryContext.cs | Preserves Added entries that replace deleted shared-identity entries during tracking-query state normalization. |
Review effort: Lite
A tracking query returning an owner could mark its replacement owned reference
Unchanged, detach the deleted original, and silently discard the pending update.