Quando scriviamo interrogazioni con LINQ, non dobbiamo mai perdere di vista ciò che in realtà esse sono, ossia alberi di funzioni e Lambda expression. Per questa ragione, un qualcosa come
1 var customers = db.Customers
2 .Where(c => c.CompanyName.StartsWith("A"))
3 .Join(db.Orders,
4 (c => c.CustomerID),
5 (o => o.CustomerID),
6 (c, o) => new { c, o })
7 .Where(co => co.o.ShippedDate != null)
8 .Select(co => co.c).Distinct();
è, grazie a puro syntactic sugar, equivalente a
1 var customersLinq = (from c in db.Customers
2 join o in db.Orders
3 on c.CustomerID equals o.CustomerID
4 where c.CompanyName.StartsWith("A") &&
5 o.ShippedDate != null
6 select c).Distinct();
Lo snippet di cui sopra infatti, non è altro che un modo leggibile per disegnare un Expression Tree. Questo concetto, che può sembrare un internal come un altro e quindi generare dei "chi se ne frega" allo stesso modo di un trattato sulle tradizioni popolari indocinesi, ha in realtà un peso determinante almeno per un paio di ragioni.
Intanto l'elaborazione non viene eseguita finchè non si cicla sul resultset; e questo, nel caso di LINQ to SQL, tanto per fare un esempio, vuol dire che finché non scriviamo
1 foreach (var item in customers)
2 {
3 Console.WriteLine(item.CompanyName);
4 }
non parte nessuna query verso il DataBase.
Inoltre, e anche in virtù anche del punto precedente, le interrogazioni LINQ possono essere concatenate tra di loro:
1 var customersStartingWithA = from c in db.Customers
2 where c.CompanyName.StartsWith("A")
3 select c;
4
5 var customersWithUnshippedOrders = (from c in customersStartingWithA
6 join o in db.Orders
7 on c.CustomerID equals o.CustomerID
8 where o.ShippedDate != null
9 select c).Distinct();
L'esempio, relativo a LINQ to SQL, genera questa query SQL:
SELECT DISTINCT [t0].[CustomerID], ....
FROM [dbo].[Customers] AS [t0]
INNER JOIN [dbo].[Orders] AS [t1] ON [t0].[CustomerID] = [t1].[CustomerID]
WHERE ([t1].[ShippedDate] IS NOT NULL) AND ([t0].[CompanyName] LIKE @p0)
che condensa perfettamente il concetto che siamo riusciti a scindere nelle due più semplici interrogazioni. Ah, attenzione che non sempre l'engine di LINQ to SQL è così smart, alle volte vengono fuori query innestate non da poco
Ovviamente quanto detto è uno dei fondamenti della stessa tecnologia LINQ, pertanto non è limitata solo a LINQ to SQL, ma a tutte le possibili incarnazioni che essa ha all'interno di .Net 3.5.
Technorati tags:
LINQ,
.Net 3.5