ich versuche zu verstehen, warum diese Linq nicht
nicht kompiliert
Der Schlüssel zum Verständnis ist, den Abschnitt der Spezifikation lesen auf wie Abfragen in normalen Code gesenkt werden.
Lassen Sie uns mit Ihrer Anfrage starten:
from fundInvoices in paidfundInvoices
from p in fundInvoices.Value
group p by p.VendorId into ps
select new Payment {
FundId = fundInvoices.Key.FundId, // ERROR here
Value = ps.Sum(p => p.Amount)
}
OK, Schritt eins. Die Regel in der Spezifikation ist:
Eine Abfrage-Ausdruck mit einer Fortsetzung wird from … into x …
in from x in (from …) …
übersetzt
Ihre Anfrage ist jetzt
from ps in (
from fundInvoices in paidfundInvoices
from p in fundInvoices.Value
group p by p.VendorId)
select new Payment {
FundId = fundInvoices.Key.FundId, // ERROR here
Value = ps.Sum(p => p.Amount)
}
Und jetzt sollte klar sein, warum fundInvoices
ist nicht in der Auswahlklausel enthalten. fundInvoices
ist eine Bereichsvariable einer völlig anderen Abfrage.
Aber falls das nicht klar ist, lass uns weitermachen. Die nächste Regel ist:
Eine Abfrage Ausdruck des Formulars wird from x in e select v
in (e) . Select (x => v)
übersetzt
Ihre Anfrage ist jetzt
((from fundInvoices in paidfundInvoices
from p in fundInvoices.Value
group p by p.VendorId))
.Select(ps =>
new Payment {
FundId = fundInvoices.Key.FundId,
Value = ps.Sum(p => p.Amount)
})
Jetzt können wir die innere Abfrage übersetzen:
Ein Abfrageausdruck mit einer zweiten from-Klausel gefolgt von s omething andere als eine select-Klausel wird from x1 in e1 from x2 in e2 …
in from * in (e1) . SelectMany(x1 => e2 , (x1 , x2) => new { x1 , x2 }) …
Die eine „transparente Kennung“ *
ist übersetzt und wir werden sehen, was es in einer Minute bedeutet.
Ihre Anfrage ist jetzt
((from * in (paidfundInvoices).SelectMany(
fundInvoices => fundInvoices.Value,
(fundInvoices, p) => new {fundInvoices, p})
group p by p.VendorId))
.Select(ps =>
new Payment {
FundId = fundInvoices.Key.FundId,
Value = ps.Sum(p => p.Amount)
})
letzte Regel:
Eine Abfrage Ausdruck der Form from x in e group v by k
in (e) . GroupBy (x => k , x => v)
übersetzt
Also das ist
((((paidfundInvoices).SelectMany(
fundInvoices => fundInvoices.Value,
(fundInvoices, p) => new {fundInvoices, p}))
.GroupBy(* => p.VendorId, * => p)))
.Select(ps =>
new Payment {
FundId = fundInvoices.Key.FundId,
Value = ps.Sum(p => p.Amount)
})
Die *
bedeutet "Bring das Paar von Mitgliedern des anonymen Typs in der Select-Many in den Geltungsbereich. Desugar dass und entfernen Sie die unnötigen Pars und wir haben die endgültige Form der Abfrage:
paidfundInvoices
.SelectMany(
fundInvoices => fundInvoices.Value,
(fundInvoices, p) => new {fundInvoices, p})
.GroupBy(pair => pair.p.VendorId, pair => pair.p)))
.Select(ps =>
new Payment {
FundId = fundInvoices.Key.FundId,
Value = ps.Sum(p => p.Amount)
})
Und jetzt sollte es sehr klar sein, warum fundInvoices
in der Fortsetzung in ihrem Umfang nicht ist. Es wäre im Bereich in der GroupBy
dank transparenter Bezeichner desugaring, aber es ist überhaupt nicht im Bereich in der Select
.
Allgemeiner: in LINQ Tive von Erklärungen auf der linken Seite zu Verwendungen auf der rechten Seite fließen im Allgemeinen, aber es gibt einige Ausnahmen: ein into
Bereichsvariablen von Umfang entfernt, sind nicht alle Bereichsvariablen an allen Stellen in ihrem Umfang ein join
Klausel und so weiter. Lesen Sie die Spezifikation für weitere Details.