-
Type:
Task
-
Resolution: Done
-
Priority:
Unknown
-
None
-
Affects Version/s: None
-
Component/s: None
-
None
-
Dotnet Drivers
-
Not Needed
-
None
-
None
-
None
-
None
-
None
-
None
Summary
Deferred from the EF-322 owned-data array-projection slice (branch EF-360). That slice made an owned entity-collection leaf in a terminal anonymous/DTO projection go native. It deliberately excludes a collection reached through an owned single-reference hop:
ctx.Blogs.AsNoTracking().Select(b => new { b.Title, b.Home.Notes })
This shape still falls back to driver-LINQ, returns correct results under Native and DriverLinq, and declines cleanly under NativeOnly. It is pinned by a tripwire test.
Why the shipped mechanism cannot cover it
The slice reads the projected array back from the $project output alias. Its admissibility rule requires the alias to equal the navigation target's containing element name, which establishes the invariant:
> the alias-addressed read and the navigation's own document-path read resolve to the same place
That invariant is load-bearing, not conservatism. The shaper is alias-addressed from translation time, but native-versus-fallback is decided later, by the compile-time gate. On the fallback path the emitted pipeline is aggregate([]), so the alias-addressed shaper receives a whole document. The read only works if the array sits at top level under the alias name.
For a hop the invariant cannot hold. The alias is necessarily flat while the document path is nested:
alias: Notes document path: Home.Notes
The alias == element name conjunct is satisfied (both are Notes), yet a top-level Notes read against a whole document misses, and a missing array coalesces to an empty collection with no error. Lifting the root-declared conjunct alone therefore reintroduces silent wrong data through a different door. This was verified during the slice: the equivalent renamed-alias bug was reproduced live, returning count=1 under Native and count=0 silently under explicit DriverLinq.
The mechanism this would need
A second read-back strategy alongside the alias-addressed one:
- Emit a path-preserving $project — MongoDB renders a dotted output field name as nested output, so projecting the path reproduces the document shape the shaper already expects.
- Keep the existing document-path read (ObjectArrayProjectionExpression) for this case rather than switching to the alias-addressed node, so the same shaper works whether or not the $project was actually emitted.
That restores the invariant by making both reads resolve to the nested path instead of a flat alias, and it is mode-independent — which a MongoQueryMode check would not be, since it would not cover a late gate decline under Native.
The cost is a second mechanism in a slice that currently has one, plus its own verification of the silent-wrong-data surface. That is why it was split out rather than folded in.
Scope
In scope: an owned collection reached through one or more OwnsOne hops, in a terminal anonymous or DTO projection, no-tracking.
Out of scope, unchanged: reference (cross-collection) collections; primitive-element collections (already native via the plain-field branch); an element type carrying its own navigation (see the separate ArgumentException ticket); and the bare spelling Select(b => b.Posts), which is additionally blocked by the SP3-wide bare-projection boundary.
Constraint any implementation inherits
Do not change the exception type or message for a reference-collection array projection leaf. Five specification tests (10 cases) assert EF Core's own InvalidOperationException carrying "could not be translated", via the upstream AssertTranslationFailed helper. Because they assert an exception type, EF_TEST_REWRITE_BASELINES cannot repair them.
Also note the sibling-readability rule the slice added: when an array leaf is present, every sibling leaf must be readable from a whole document. A path-preserving mechanism will need its own equivalent, since the reasoning is the same.
Provenance
Design, spike findings and plan are committed in the repo:
docs/superpowers/specs/2026-07-29-native-array-valued-projections-design.md docs/superpowers/specs/2026-07-29-native-array-valued-projections-spike-findings.md docs/superpowers/plans/2026-07-29-native-array-valued-projections.md
The decision to defer this item was taken on 2026-07-30 during execution of that plan.