遅延読み込みと即時読み込み
オブジェクトに対してクエリを実行すると、要求したオブジェクトだけが実際に取得されます。 "関連" オブジェクトが同時に自動的にフェッチされることはありません。 (詳しくは、「リレーションシップを介したクエリの実行」をご覧ください。)ただし、関連オブジェクトにアクセスしようとすると、それらを取得する要求が生成されるため、関連オブジェクトがまだ読み込まれていない状態を識別することはできません。
たとえば、特定の注文のセットを取得するクエリを実行し、そのうちの一部についてだけ特定の顧客にメール通知を送信するものとします。 最初から注文ごとにすべての顧客データを取得する必要はありません。 遅延読み込みを使用すると、関連情報が実際に必要になるまで、その情報の取得を遅らせることができます。 次に例を示します。
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
1 つのクエリでクロス積によって顧客データと注文データを結合し、すべての関連データを大きな 1 つの投影として取得することもできます。 ただし、このような結果はエンティティではありません (詳しくは、「LINQ to SQL オブジェクト モデル」をご覧ください)。 エンティティとは、識別子を持ち、変更が可能なオブジェクトですが、これらの結果は投影であり、変更や永続化はできません。 さらに、平坦な結合出力では、注文ごとに各顧客が繰り返し現れるため、余分なデータが大量に取得されることになります。
ここで必要なのは、関連オブジェクトのセットを同時に取得することです。 このセットは、目的の用途に必要十分なデータだけを取得できるように、グラフ上に線引きされた区画に相当します。 この目的のため、LINQ to SQL には、オブジェクト モデルの特定の領域の即時読み込みを行う DataLoadOptions が用意されています。 次のメソッドがあります。
LoadWith メソッド。メイン ターゲットに関連するデータを即時に読み込みます。
AssociateWith メソッド。特定のリレーションシップに対して取得されるオブジェクトにフィルターを適用します。