Fix NullReferenceException materializing JSON owned collections with nested primitive collections under lazy-loading proxies#38473
Open
Copilot wants to merge 2 commits into
Conversation
…primitive collection Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix NullReferenceException in IncludeJsonEntityCollection with UseLazyLoadingProxies
Fix NullReferenceException materializing JSON owned collections with nested primitive collections under lazy-loading proxies
Jun 19, 2026
There was a problem hiding this comment.
Pull request overview
Fixes a NullReferenceException during relational JSON materialization when lazy-loading proxies are enabled and a JSON-owned collection element contains a nested primitive collection. The fix aligns the primitive-collection population rewrite with other property assignments by deriving the target instance from the original assignment (node.Left) rather than the converted instance variable which can still be null under proxies.
Changes:
- Update
ValueBufferTryReadValueMethodsReplacerto read the existing primitive-collection property value from the original assignment target instance (proxy instance) instead of the convertedinstance. - Extend the lazy-loading-proxies JSON test model with an
IList<long>primitive collection and seed data. - Add a regression test that reproduces the proxy + nested primitive-collection scenario and asserts correct materialization.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| test/EFCore.Specification.Tests/Query/AdHocJsonQueryTestBase.cs | Adds a regression test and extends the lazy-loading-proxies JSON-owned model/seed data with a nested primitive collection. |
| src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs | Fixes instance selection for primitive-collection population under proxies to avoid dereferencing a not-yet-assigned converted instance. |
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 #28688
An owned collection mapped to JSON (
OwnsMany(...).ToJson()) whose element contains a nested primitive collection (e.g.IList<long>) threwNullReferenceExceptionin the JSON shaper — but only whenUseLazyLoadingProxies()was enabled. Disabling either proxies or the nested collection avoided the failure.Root cause
In the proxy case, the JSON entity materializer rewriter normalizes the materializer to introduce a converted (non-proxy) variable holding
(MyEntity)proxyInstance, which is assigned only at the end of the block.ValueBufferTryReadValueMethodsReplacerrebuilds the primitive-collection populate logic against that variable (instance), so reading the member off it while it was stillnullthrew. Every other property assignment worked because it is rebuilt off the original assignment'snode.Left(the proxy instance).Changes
ShaperProcessingExpressionVisitor— the primitive-collection branch inValueBufferTryReadValueMethodsReplacer.VisitBinarynow derives its target instance fromnode.Left(the proxy instance), falling back toinstance, matching how all other property assignments are rewritten:AdHocJsonQueryTestBase— extended the existing lazy-loading-proxies JSON model with a nestedIList<long>and addedProject_proxies_entity_with_json_with_primitive_collection, which reproduces the NRE without the fix.