Отложенная и немедленная загрузка

При запросе объекта фактически извлекается только запрошенный объект. Связанные объекты одновременно не извлекаются автоматически. (Дополнительные сведения см. в разделе Запрос между связями.) Невозможно увидеть тот факт, что связанные объекты еще не загружены, так как попытка доступа к ним создает запрос, который извлекает их.

Например, может потребоваться запросить определенный набор заказов, а затем только иногда отправлять уведомление по электронной почте определенным клиентам. В этом случае не требуется сразу извлекать все данные о клиентах вместе с каждым заказом. Можно использовать отложенную загрузку для получения дополнительной информации только тогда, когда она действительно необходима. Рассмотрим следующий пример:

    Northwnd db = new Northwnd(@"northwnd.mdf");

    IQueryable<Order> notificationQuery =
    from ord in db.Orders
 where ord.ShipVia == 3
  select ord;

    foreach (Order ordObj in notificationQuery)
    {
        if (ordObj.Freight > 200)
            SendCustomerNotification(ordObj.Customer);
        ProcessOrder(ordObj);
    }
}
Dim db As New Northwnd("c:\northwnd.mdf")
Dim notificationQuery = _
    From ord In db.Orders _
    Where ord.ShipVia = 3 _
    Select ord

For Each ordObj As Order In notificationQuery
    If ordObj.Freight > 200 Then
        SendCustomerNotification(ordObj.Customer)
        ProcessOrder(ordObj)
    End If

Next

Иногда бывает полезным реализовать и противоположный подход. Предположим, имеется приложение, которому требуется одновременно просматривать данные о клиентах и заказах. В этом случае необходимы оба набора данных. Поскольку приложению требуются сведения о заказах для каждого клиента в момент получения результатов, нецелесообразно отправлять отдельные запросы на получение заказов для каждого клиента. Более эффективно извлекать данные о заказах одновременно с данными о клиентах.

Northwnd db = new Northwnd(@"c:\northwnd.mdf");

db.DeferredLoadingEnabled = false;

IQueryable<Customer> custQuery =
    from cust in db.Customers
    where cust.City == "London"
    select cust;

foreach (Customer custObj in custQuery)
{
    foreach (Order ordObj in custObj.Orders)
    {
        ProcessCustomerOrder(ordObj);
    }
}
Dim db As New Northwnd("c:\northwnd.mdf")

db.DeferredLoadingEnabled = False

Dim custQuery = _
    From cust In db.Customers _
    Where cust.City = "London" _
    Select cust

For Each custObj As Customer In custQuery
    For Each ordObj As Order In custObj.Orders
        ProcessCustomerOrder(ordObj)
    Next
Next

Можно также объединить клиентов и заказы в одном запросе путем создания перекрестного произведения и извлечения всех связанных битов данных в виде одной большой проекции. Однако эти результаты не являются сущностями (Дополнительные сведения см. в разделе Объектная модель LINQ to SQL). Сущности представляют собой объекты, которые обладают идентификациями и которые можно изменить. Результаты, напротив, являются проекциями, и их нельзя ни изменить, ни сохранить. Более того, при таком подходе извлекается большое количество избыточных данных, поскольку в плоских выходных данных, полученных в результате объединения, каждый клиент повторяется в каждом заказе.

Действительно эффективным стал бы способ параллельного извлечения набора связанных объектов. Этот набор является отделенным разделом графа, поэтому пользователь извлекает ровно тот объем данных, который ему необходим. Для этого LINQ to SQL обеспечивает DataLoadOptions немедленную загрузку области объектной модели. Ниже перечислены используемые методы.

  • Метод LoadWith для немедленной загрузки данных, связанных с основным целевым объектом.

  • Метод AssociateWith для фильтрации объектов, извлеченных для определенной связи.

См. также