Realizar consultas en varias relaciones (LINQ to SQL)
Actualización: November 2007
Las referencias a otros objetos o colecciones de otros objetos en sus definiciones de clase se corresponden directamente con relaciones de clave externa en la base de datos. Puede utilizar estas relaciones cuando realice consultas utilizando la notación de punto para tener acceso a las propiedades de la relación y navegar entre los objetos. Estas operaciones de acceso se convierten en combinaciones más complejas o subconsultas correlacionadas en el código SQL equivalente.
Por ejemplo, la consulta siguiente navega de pedidos a clientes como una manera de restringir los resultados a sólo los pedidos de los clientes de Londres.
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;
Si no existieran propiedades de relación, tendría que escribirlas manualmente como combinaciones, como lo haría en una consulta SQL y como muestra el código siguiente:
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;
Puede utilizar la propiedad de relación para definir esta relación concreta una vez. Después, puede utilizar la sintaxis de punto más apropiada. Sin embargo, la existencia de las propiedades de relación es más importante porque los modelos de objetos específicos del dominio se definen normalmente como jerarquías o gráficos. Los objetos para los que programa tienen referencias a otros objetos. Es una mera coincidencia que las relaciones de objeto a objeto se correspondan con tipos de relaciones de clave externa en las bases de datos. Por ello, el acceso de propiedad proporciona una manera apropiada de escribir combinaciones.
A este respecto, las propiedades de relación son más importantes en el lado de los resultados de una consulta que como parte de la propia consulta. Una vez que la consulta ha recuperado los datos sobre un cliente determinado, la definición de clase indica que los clientes tienen pedidos. En otras palabras, se espera que la propiedad Orders de un cliente determinado sea una colección que se llena con todos los pedidos de ese cliente. De hecho, esa era su intención cuando definió las clases de esta manera. Espera ver allí los pedidos aun cuando la consulta no los ha solicitado. Espera que su modelo de objetos refleje lo que en realidad se encuentra en una extensión en memoria de la base de datos, con los objetos relacionados inmediatamente disponibles.
Ahora que tiene las relaciones, puede escribir consultas haciendo referencia a las propiedades de relación definidas en las clases. Estas referencias de relación se corresponden con las relaciones de clave externa de la base de datos. Las operaciones que utilizan estas relaciones se convierten en combinaciones más complejas en el código SQL equivalente. Siempre y cuando haya definido una relación (mediante el atributo AssociationAttribute ), no tiene que codificar una combinación explícita en LINQ to SQL.
Para ayudar a mantener esta ilusión, LINQ to SQL implementa una técnica denominada carga aplazada. Para obtener más información, vea Comparación entre carga aplazada y carga inmediata (LINQ to SQL).
Considere la consulta SQL siguiente para proyectar una lista de pares 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)
La ilustración siguiente muestra gráficamente la relación entre las tablas.
Para obtener los mismos resultados en LINQ to SQL, utilice la referencia de propiedad Orders que ya existe en la clase Customer. La referencia Orders proporciona la información necesaria para ejecutar la consulta y proyectar los pares CustomerID-OrderID, como en el código siguiente:
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 };
También puede hacer lo contrario. Es decir, puede consultar Orders y utilizar su referencia de relación Customer para tener acceso a información sobre el objeto Customer asociado. El código siguiente proyecta los mismos pares CustomerID-OrderID que antes, pero esta vez se consulta Orders en lugar de 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 };