Consultando entre relacionamentos
As referências a outros objetos ou coleções de outros objetos em suas definições de classe correspondem diretamente a relações de chave estrangeira no banco de dados. Você pode usar essas relações ao consultar usando a notação de pontos para acessar as propriedades da relação e navegar de um objeto para outro. Essas operações de acesso se traduzem em junções mais complexas ou subconsultas correlacionadas no SQL equivalente.
Por exemplo, a consulta a seguir navega de pedidos para clientes como uma forma de restringir os resultados apenas aos pedidos de clientes localizados em Londres.
Northwnd db = new Northwnd(@"northwnd.mdf");
IQueryable<Order> londonOrderQuery =
from ord in db.Orders
where ord.Customer.City == "London"
select ord;
Dim db As New Northwnd("c:\northwnd.mdf")
Dim londonOrderQuery = _
From ord In db.Orders _
Where ord.Customer.City = "London" _
Select ord
Se as propriedades de relacionamento não existissem, você teria que escrevê-las manualmente como junções, assim como faria em uma consulta SQL, como no código a seguir:
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;
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
Você pode usar a propriedade relationship para definir essa relação específica uma vez. Em seguida, você pode usar a sintaxe de pontos mais conveniente. Mas as propriedades de relacionamento existem mais importante porque os modelos de objeto específicos do domínio são normalmente definidos como hierarquias ou gráficos. Os objetos que você programa contra têm referências a outros objetos. É apenas uma feliz coincidência que as relações objeto-a-objeto correspondam a relações de estilo de chave estrangeira em bancos de dados. O acesso à propriedade fornece uma maneira conveniente de escrever junções.
Com relação a isso, as propriedades de relacionamento são mais importantes no lado dos resultados de uma consulta do que como parte da própria consulta. Depois que a consulta tiver recuperado dados sobre um cliente específico, a definição de classe indica que os clientes têm pedidos. Em outras palavras, você espera que a Orders
propriedade de um determinado cliente seja uma coleção que é preenchida com todos os pedidos desse cliente. Esse é, de facto, o contrato que declarou ao definir as classes desta forma. Você espera ver os pedidos lá, mesmo que a consulta não solicite pedidos. Você espera que seu modelo de objeto mantenha uma ilusão de que é uma extensão na memória do banco de dados com objetos relacionados imediatamente disponíveis.
Agora que você tem relações, pode escrever consultas consultando as propriedades de relacionamento definidas em suas classes. Essas referências de relacionamento correspondem a relações de chave estrangeira no banco de dados. As operações que usam essas relações se traduzem em junções mais complexas no SQL equivalente. Contanto que você tenha definido um relacionamento (usando o AssociationAttribute atributo), não é necessário codificar uma junção explícita no LINQ to SQL.
Para ajudar a manter essa ilusão, o LINQ to SQL implementa uma técnica chamada carregamento diferido. Para obter mais informações, consulte Carregamento adiado versus imediato.
Considere a seguinte consulta SQL para projetar uma lista de CustomerID
-OrderID
pares:
SELECT t0.CustomerID, t1.OrderID
FROM Customers AS t0 INNER JOIN
Orders AS t1 ON t0.CustomerID = t1.CustomerID
WHERE (t0.City = @p0)
Para obter os mesmos resultados usando LINQ to SQL, use a referência de Orders
propriedade já existente na Customer
classe. A Orders
referência fornece as informações necessárias para executar a consulta e projetar os CustomerID
-OrderID
pares, como no código a seguir:
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 };
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
Você também pode fazer o inverso. Ou seja, você pode consultar Orders
e usar sua Customer
referência de relacionamento para acessar informações sobre o objeto associado Customer
. O código a seguir projeta os mesmos CustomerID
-OrderID
pares que antes, mas desta vez consultando Orders
em vez de .Customers
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 };
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