Skip to content

Fix DetectChanges throwing when nullable nested complex property with nested collection is set to null#38667

Open
AndriySvyryd with Copilot wants to merge 2 commits into
mainfrom
copilot/fix-complexcollection-tojson-issue
Open

Fix DetectChanges throwing when nullable nested complex property with nested collection is set to null#38667
AndriySvyryd with Copilot wants to merge 2 commits into
mainfrom
copilot/fix-complexcollection-tojson-issue

Conversation

Copilot AI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Fixes #38632

Setting a nullable complex property to null during change detection throws InvalidOperationException: "must be initialized to a non-null value" when that property's type contains a collection with 2+ items, inside a ComplexCollection mapped with ToJson().

Root cause: InternalComplexCollectionEntry.GetEntry() checked whether the CLR collection was null before checking if a tracked entry already existed in _entries. During RemoveEntry's ordinal reindexing loop, the tracked entries are valid in-memory even though the parent CLR collection is null (because its parent complex property was just nulled out). With 1 item the reindex loop body never runs; with 2+ items it does, triggering GetEntry → null check → throw.

// Entity shape that triggers the bug:
entity.Items[0].Meta = null; // Meta.Entries had 2+ items
await context.SaveChangesAsync(); // throws before fix, saves correctly after

Changes:

  • InternalEntryBase.InternalComplexCollectionEntry.cs — In GetEntry, move the _entries/_originalEntries lookup before the null CLR collection check. Existing tracked entries are returned directly, bypassing the (now-irrelevant) null check.
  • ComplexCollectionJsonUpdateTestBase.cs — New model (EntityWithNullableMeta / ItemWithMeta / OptionalMeta / MetaEntry), seed data, and test Set_nullable_complex_property_with_nested_collection_to_null that exercises the 2-item path.
  • ComplexCollectionJsonUpdateSqliteTest.cs / ComplexCollectionJsonUpdateSqlServerTest.cs — Provider-specific overrides with SQL assertions.

… nested collection is set to null

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix ComplexCollection + ToJson() throws InvalidOperationException Fix DetectChanges throwing when nullable nested complex property with nested collection is set to null Jul 17, 2026
Copilot AI requested a review from AndriySvyryd July 17, 2026 05:19
@AndriySvyryd
AndriySvyryd requested a review from Copilot July 17, 2026 23:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an InvalidOperationException thrown during change detection when a nullable nested complex property (containing a nested collection) is set to null inside a JSON-mapped complex collection (ToJson()), by ensuring existing tracked entries are consulted before validating CLR collection initialization.

Changes:

  • Adjust InternalComplexCollectionEntry.GetEntry to return existing tracked entries before checking whether the underlying CLR collection is null, enabling ordinal reindexing during cleanup.
  • Add a relational specification test model/seed + test coverage for the nullable complex property + nested collection scenario (2+ items path).
  • Add provider-specific SQL assertions for SQLite and SQL Server.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/EFCore/ChangeTracking/Internal/InternalEntryBase.InternalComplexCollectionEntry.cs Fixes GetEntry ordering to avoid throwing during cleanup/reindexing when parent CLR collection is null but tracked entries still exist.
test/EFCore.Relational.Specification.Tests/Update/ComplexCollectionJsonUpdateTestBase.cs Adds new model/seed and a regression test covering nullable complex property nulled out with nested collection having 2+ elements.
test/EFCore.Sqlite.FunctionalTests/Update/ComplexCollectionJsonUpdateSqliteTest.cs Adds SQLite SQL baseline assertion for the new regression test.
test/EFCore.SqlServer.FunctionalTests/Update/ComplexCollectionJsonUpdateSqlServerTest.cs Adds SQL Server SQL baseline assertion for the new regression test.

@AndriySvyryd
AndriySvyryd marked this pull request as ready for review July 18, 2026 01:09
@AndriySvyryd
AndriySvyryd requested a review from a team as a code owner July 18, 2026 01:09
@AndriySvyryd
AndriySvyryd requested a review from cincuranet July 18, 2026 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants