Esecuzione di una query tra relazioni (LINQ to SQL)
I riferimenti ad altri oggetti o raccolte di altri oggetti nelle definizioni della classe corrispondono direttamente alle relazioni di chiavi esterne nel database. È possibile utilizzare queste relazioni quando si esegue una query utilizzando la notazione del punto per accedere alle proprietà della relazione e spostarsi tra gli oggetti. Queste operazioni di accesso vengono convertite in join più complessi o sottoquery correlate nell'equivalente SQL.
Ad esempio, utilizzando la query seguente è possibile spostarsi da ordini a clienti per limitare i risultati solo agli ordini per i clienti residenti nell'area londinese.
Dim db As New Northwnd("c:\northwnd.mdf")
Dim londonOrderQuery = _
From ord In db.Orders _
Where ord.Customer.City = "London" _
Select ord
Northwnd db = new Northwnd(@"northwnd.mdf");
IQueryable<Order> londonOrderQuery =
from ord in db.Orders
where ord.Customer.City == "London"
select ord;
Se le proprietà della relazione non esistessero, sarebbe necessario scriverle manualmente come join, esattamente come in una query SQL, come nel codice seguente:
Dim db As New Northwnd("c:\northwnd.mdf")
Dim londOrderQuery = _
From cust In db.Customers _
Join ord In db.Orders On cust.CustomerID Equals ord.CustomerID _
Select ord
Northwnd db = new Northwnd(@"northwnd.mdf");
IQueryable<Order> londonOrderQuery =
from cust in db.Customers
join ord in db.Orders on cust.CustomerID equals ord.CustomerID
where cust.City == "London"
select ord;
È possibile utilizzare la proprietà della relazione per definire questa particolare relazione una sola volta, quindi utilizzare la più pratica sintassi del punto. Le proprietà della relazione esistono tuttavia soprattutto perché i modelli a oggetti specifici del dominio sono in genere definiti come gerarchie o grafici. Gli oggetti utilizzati nella programmazione dispongono di riferimenti ad altri oggetti. È solo una coincidenza che le relazioni da oggetto a oggetto corrispondano alle relazioni di tipo chiave esterna nei database. L'accesso alle proprietà offre quindi un modo pratico per scrivere join.
A questo riguardo, le proprietà della relazione sono più importanti sul lato dei risultati di una query anziché nella query stessa. Dopo il recupero dei dati su un cliente particolare tramite la query, la definizione della classe indica che sono presenti ordini. In altre parole, si prevede che la proprietà Orders di un particolare cliente sia una raccolta popolata con tutti gli ordini di tale cliente. Si tratta in effetti del contratto dichiarato definendo le classi in questo modo. Si prevede che nei risultati siano inclusi gli ordini, anche se non sono stati espressamente richiesti nella query. Si prevede che il modello a oggetti appaia come un'estensione in memoria del database con gli oggetti correlati immediatamente disponibili.
Dopo avere creato le relazioni, è possibile scrivere query facendo riferimento alle proprietà delle relazioni definite nelle classi. Questi riferimenti alle relazioni corrispondono alle relazioni di chiave esterna nel database. Le operazioni che utilizzano queste relazioni vengono convertite in join più complessi nell'equivalente SQL. A condizione che sia stata definita una relazione utilizzando l'attributo AssociationAttribute, non sarà necessario codificare un join esplicito in LINQ to SQL.
Per mantenere questa apparenza, in LINQ to SQL viene implementata una tecnica detta caricamento posticipato. Per ulteriori informazioni, vedere Caricamento rinviato e immediato (LINQ to SQL).
Si consideri la query SQL seguente per la proiezione di un elenco di coppie CustomerID- OrderID:
SELECT t0.CustomerID, t1.OrderID
FROM Customers AS t0 INNER JOIN
Orders AS t1 ON t0.CustomerID = t1.CustomerID
WHERE (t0.City = @p0)
Nella figura seguente è illustrata graficamente la relazione tra tabelle.
Per ottenere gli stessi risultati tramite LINQ to SQL, utilizzare il riferimento alla proprietà Orders esistente nella classe Customer. Il riferimento a Orders fornisce le informazioni necessarie per eseguire la query e creare una proiezione delle coppie CustomerID-OrderID, come nel codice seguente:
Dim db As New Northwnd("c:\northwnd.mdf")
Dim idQuery = _
From cust In db.Customers, ord In cust.Orders _
Where cust.City = "London" _
Select cust.CustomerID, ord.OrderID
Northwnd db = new Northwnd(@"northwnd.mdf");
var idQuery =
from cust in db.Customers
from ord in cust.Orders
where cust.City == "London"
select new { cust.CustomerID, ord.OrderID };
È inoltre possibile procedere in senso inverso, ovvero eseguire una query su Orders e utilizzare il relativo riferimento alla relazione di Customer per accedere alle informazioni sull'oggetto Customer associato. Nel codice seguente vengono proiettate le stesse coppie CustomerID-OrderID come nell'esempio precedente, ma in questo caso eseguendo una query su Orders anziché su Customers.
Dim db As New Northwnd("c:\northwnd.mdf")
Dim idQuery = _
From ord In db.Orders _
Where ord.Customer.City = "London" _
Select ord.CustomerID, ord.OrderID
Northwnd db = new Northwnd(@"northwnd.mdf");
var idQuery =
from ord in db.Orders
where ord.Customer.City == "London"
select new { ord.Customer.CustomerID, ord.OrderID };