Выполнение запросов в связях (LINQ to SQL)
Обновлен: November 2007
Ссылки на другие объекты или коллекции других объектов в определениях классов указывают непосредственно на связи внешнего ключа в базе данных. Эти связи можно использовать при осуществлении запроса с помощью точечной нотации для доступа к свойствам связей и перехода от одного объекта к другому. Эти операции доступа преобразуются в более сложные соединения или коррелированные подзапросы в эквивалентном SQL.
Например, следующий запрос переходит от заказов к клиентам в качестве способа ограничения результатов только заказами для клиентов, находящихся в Лондоне.
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;
Если свойства связи не существуют, придется написать их вручную как соединения. Это выполняется так же, как и в запросе SQL — см. следующий код.
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;
Свойство связи можно использовать для однократного определения данной конкретной связи. После этого можно применять более удобный точечный синтаксис. Однако существование свойств связи более важно, поскольку объектные модели, характерные для доменов, обычно определяются как иерархии или графики. Программируемые объекты имеют ссылки на другие объекты. Соответствие связей "объект-объект" связям внешнего ключа в базах данных является лишь совпадением. Доступ к свойству предоставляет удобный способ для написания соединений.
В связи с этим свойства связи являются более важными как результаты запроса, чем как часть самого запроса. После того, как запрос извлечет, данные о конкретном клиенте, определение класса указывает наличие заказов. Другими словами, ожидается, что свойство Orders конкретного клиента является коллекцией, заполняемой всеми заказами данного клиента. На самом деле это контракт, объявленный путем подобного определения классов. Вы хотите увидеть в нем заказы, даже если они не требуются для запроса. Вы хотите, чтобы объектная модель поддерживала представление о том, что это находящееся в памяти расширение базы данных со связанными и немедленно доступными объектами.
Теперь при наличии связей можно писать запросы, обращаясь к свойствам связей, определенным в классах. Эти ссылки на связи соответствуют связям внешнего ключа в базе данных. Операции, использующие эти связи, преобразуются в более сложные соединения в эквивалентном SQL. После определения связи (с помощью атрибута AssociationAttribute) не требуется кодировать явное соединение в LINQ to SQL.
Для поддержки этого представления в LINQ to SQL существует метод, называемый отложенной загрузкой. Дополнительные сведения см. в разделе Сравнение отложенной и немедленной загрузки (LINQ to SQL).
Рассмотрим следующий запрос SQL для создания списка пар 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)
На следующем рисунке табличная связь представлена графически.
Чтобы получить такие же результаты с помощью LINQ to SQL, используйте ссылку на свойство Orders, уже существующую в классе Customer. Ссылка Orders предоставляет данные, необходимые для выполнения запроса и создания пар CustomerID-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
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 };
Также можно выполнить обратное. Это значит, что можно запросить Orders и использовать ссылку на связь Customer для получения сведений о связанном объекте Customer. В следующем коде создаются те же пары CustomerID-OrderID, что и ранее, однако на этот раз выполняется запрос Orders, а не 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 };