推迟加载与即时加载

查询某对象时,实际上您只检索请求的对象。 不会同时自动提取相关对象。 (有关详细信息,请参阅跨关系查询。)你无法看到相关对象尚未加载这一事实,原因是尝试访问它们时将产生检索它们的请求。

例如,您可能需要查询一组特定的订单,然后偶而向特定客户发送电子邮件通知。 您最初不一定需要检索与每个订单有关的所有客户数据。 您可以使用延迟加载将额外信息的检索操作延迟到您确实需要检索它们时再进行。 请考虑以下示例:

    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 方法,用于筛选为特定关系检索到的对象。

请参阅