延後和立即載入的比較
當您查詢物件時,實際上只擷取了所要求的物件。 不會同時自動擷取「相關」物件。 (如需詳細資訊,請參閱跨關聯性查詢。)因為嘗試存取相關物件會產生對相關物件進行擷取的要求,所以您看不到相關物件尚未載入的事實。
例如,您可能會想要查詢一組特定訂單,然後只偶爾將電子郵件通知傳送給特定客戶。 因此並不需要一開始就擷取每筆訂單的所有客戶資料。 您可以使用延後載入,將確切資訊的擷取延後至絕對需要的時候才進行擷取。 請考慮下列範例:
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
您也可以建立叉積查詢,並將資料的所有相對位元都擷取為一個大型投影 (Projection),以利用查詢來聯結 (Join) 客戶和訂單。 但這些結果不是實體 (Entity) (如需詳細資訊,請參閱 LINQ to SQL 物件模型)。 實體是具有識別 (Identity) 而且可以修改的物件,而上述結果卻是無法變更和持續 (Persist) 的投影。 更糟的是,因為每位客戶會以簡維聯結輸出重複每筆訂單,所以您會擷取到許多多餘的資料。
您實際需要的是一種可以同時擷取一組相關物件的方式。 而這組物件是圖形的明確部分,因此您擷取到的資料就會是您所需要的資料。 因此,LINQ to SQL 會提供 DataLoadOptions,以立即載入物件模型的區域。 方法如下:
LoadWith 方法,可以立即載入與主要目標相關的資料。
AssociateWith 方法,可以篩選針對特定關聯性 (Relationship) 所擷取的物件。