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