Поделиться через


Сравнение отложенной и немедленной загрузки (LINQ to SQL)

Обновлен: November 2007

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

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

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(@"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")

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
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);
    }
}

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

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

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

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

См. также

Другие ресурсы

Основные понятия о запросах в LINQ to SQL