Query: whole non-entity object from a plain (non-aggregated) LeftJoin/DefaultIfEmpty inner is not nulled on no-match
I maintainer di solito rispondono entro 2 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 30/100
Direzione di ricerca
Inizia con la revisione dell’espansione della navigazione in #32957/#37859 e traccia come PendingSelector viene ripiegato prima di AddJoin. Riproduci il Select semplice non aggregato con LeftJoin o GroupJoin più DefaultIfEmpty, quindi confrontalo con la navigazione opzionale e con gli altri casi di #22517. Il lavoro è completato quando l’intero oggetto è null in assenza di corrispondenze, senza introdurre regressioni nella compensazione della navigazione opzionale.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Sub-case of #22517. Prior report: #26873 (closed as duplicate). This one is filed to track the specific plain-inner variant, which — unlike its siblings — cannot be fixed with the narrow relational marker and should be tackled as part of the navigation-expansion rework (#32957 / #37859).
Repro shape
A whole non-entity object projected from the nullable side of a LeftJoin / GroupJoin+DefaultIfEmpty, where the inner is a plain (non-aggregated) Select:
var categories = context.Requests.Select(r => new { r.PickupStatusId, Count = 1 });
var query = context.Statuses
.LeftJoin(categories, s => s.PickupStatusId, c => c.PickupStatusId, (s, countInfo) => new { s.PickupStatusId, countInfo });
On a no-match row this throws Nullable object must have a value instead of yielding a null countInfo. Same shape via GroupJoin + DefaultIfEmpty.
Root cause
Navigation expansion folds the trivial inner Select into the pending selector and moves the projection forward. So at AddJoin the inner shaper is the raw entity, not a New/MemberInit. The #30915 marker gate is conditioned on the inner shaper being New/MemberInit, so the marker is never injected. Nothing gates the object at materialization.
Why this cannot be fixed in the relational layer
Two relational-layer approaches were tried and rejected:
- Inject the marker at
AddJoin. The code path never runs — the inner shaper is already a bare entity by the timeAddJoinsees it. - Gate at projection-binding time instead. This false-positives on ordinary optional-navigation projections (
Select(x => new { x.OptionalNav.Prop })): it nulls the whole object instead of the member, defeating optional-navigation type compensation. Confirmed regression on 8GearsOfWarQuerytests.
After folding, the whole-DefaultIfEmpty'd-element case is structurally identical to an optional-navigation member access. The distinguishing signal is PendingSelector, which is a core-only concept, invisible to providers, and erased before translation runs. No relational-layer rule can recover it.
Conclusion
The marker gate needs the inner projection to still be a New/MemberInit at translation time; folding removes that precondition. Removing/reworking navigation expansion dissolves the fold — the projection reaches translation as written, the marker fires, and the optional-navigation case stays distinct. This variant belongs in that work, not a narrow relational fix.
The other #22517 sub-cases (struct/record-struct whole object #30915, GroupBy-after-join #28119, value-type left-join default #38555) do not fold and remain fixable narrowly; they are unaffected.
- Lingua principale
- C#
- Stelle
- 14.8k
- Fork
- 3.4k
- Merge medio
- 3g 18h
- PR unite (30g)
- 159
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di dotnet/efcore
-
customer-reported
Difficoltà 4/5 3-5 giorni Idoneità per principianti 54/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 2 giorni
-
Regression in 11.0: replacing an owned instance or re-adding an entity with the same key sets unchanged OnAdd properties to nullForse già presa @seragAhmed l’ha presa oggi. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
dotnet/efcore#39617 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
customer-reported
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di dotnet/efcore
Issue simili
-
bug emitter:client:csharp
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
microsoft/typespec#12572 · 1 commento · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
needs-area-label
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 2 giorni
-
AWS Lambda: KeyNotFoundException drops HTTP-triggered transactions when allowAllHeaders is disabledApertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
newrelic/newrelic-dotnet-agent#3949 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
area-networking
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
dotnet/aspnetcore#70545 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 87/100
I maintainer di solito rispondono entro 1 giorno