perché non potevano i progettisti di Linq rendere le cose semplici (più sql come)
Avrebbero potuto. Ma la tua definizione di semplice (come un programmatore sql) non è la stessa della semplice definizione del programmatore OO. Linq (in C#) è una tecnologia di query per i programmatori OO, in primo luogo. Un esempio di questo è perché selezionare viene l'ultimo. Questo è per soddisfare le regole di ambito in C# e il supporto intellisense nell'editor.
Questi programmatori potrebbero non ottenere LEFT JOIN
(e diventare davvero confusi se si dice LEFT OUTER JOIN
- pensare che ci sia qualche differenza, come se uno erediti dall'altro).
Quello che capiscono è GROUP JOIN
, che si comporta in modo simile.
List<int> myInts = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<int> myOtherInts = new List<int>() { 1, 3, 5, 7, 9, 11, 13 };
//
var query = from i in myInts
join j in myOtherInts on i equals j into g
select new {key = i, myGroup = g};
//
foreach (var grouping in query)
{
Console.WriteLine("--{0}", grouping.key);
foreach (var x in grouping.myGroup)
Console.WriteLine(x);
}
Tutto ciò che DefaultIfEmpty
roba non fa altro che scompattare il gruppo - appiattendo i risultati in riga/colonna forma - lontano da naturale forma gerarchica del programmatore OO.DefaultIfEmpty
non è semanticamente necessario per ottenere i risultati.
Ecco la stessa query in forma di metodo - che il compilatore genera da quanto sopra, e che io preferisco:
var query = myInts.GroupJoin(
myOtherInts,
i => i,
j => j,
(i, g) => new { key = i, myGroup = g }
);
Potrebbe affermare che dal punto di vista il suo esempio?
Questa query offre ai clienti, con i loro ordini, una raccolta allegata. La raccolta ordini potrebbe essere vuota. Se hai 50 clienti e 1000 ordini, avrai 50 clienti nel risultato.
from c in dc.Customers
join o in dc.Orders on c.custid equals o.custid into someOrders
select new CustomerWithOrders()
{theCustomer = c, theOrders = someOrders};
Questa query fornisce una riga CustomerOrder. Se un cliente ha 5 ordini, il cliente apparirà 5 volte, ogni volta abbinato a un ordine diverso. Se il cliente ha 0 ordini, il cliente apparirà una volta abbinato a un ordine nullo. Se hai 50 clienti e 1000 ordini, avrai 50-1049 righe dopo il join e il significato di un elemento nel risultato è difficile da definire.
from c in dc.Customers
join o in dc.Orders on c.custid equals o.custid into temp
from x in temp.DefaultIfEmpty()
select new CustomerOrderHybrid() {theCustomer = c, theOrder = x}
Se attuate left join
, richiederebbe la forma risultato del secondo esempio. Una volta utilizzato lo group join
, che è meglio, non implementerei lo left join
in un solo passaggio. La modellazione gerarchica dei risultati della query è ottima.
Sì, ho intuito che probabilmente era difficile - mi piacerebbe sapere perché è stato difficile però ... – user52110
Linq non è zucchero sintattico. il compilatore non traduce nulla nelle espressioni lambda. Nessuno ha detto nulla sulla creazione di SQL nella domanda. -1 –
OK, non sono sicuro che sia lambda di per sé, ma linq è zucchero sintattico, e viene tradotto in chiamate di metodo dal compilatore. –