マップしようとしているとき、またはマップしないときは、Aを選択します。ナビゲーションプロパティには多くの利点があり(などCustomer.Supplier
)、遅延/熱心な読み込みを制御する方法はたくさんあります。
ナビゲーションプロパティの利点は、linqクエリの記述がはるかに簡単なことです。結合を作成する必要はほとんどありません。
参加あり:
from supp in db.Supliers
join serv in db.Services on supp.SupplierId equals serv.SupplierId
select ...
ナビゲーションプロパティ付き
from supp in db.Supliers
from serv in supp.Services
select ...
またはこのようなもの:
from supp in db.Supliers
select new { supp.Name, ServicesCount = supp.Services.Count() }
EFは、SQLで結合を行う方法を理解します。
ナビゲーションプロパティがあるからといって、常に読み込まれるわけではありません。遅延読み込みを行うには、2つの条件が満たされている必要があります
virtual
プロパティは、EFが遅延読み込みを実行するための配線を使用してプロキシタイプでオーバーライドできるように定義する必要があります。
- コンテキストで遅延読み込みを有効にする必要があります。これらはデフォルトですが、を設定することでインスタンスごとにオフにすることができます
context.Configuration.LazyLoadingEnabled = false
。
したがって、これは遅延読み込みを制御する2つの方法も示しています。構造的または一時的に有効/無効にできます。
それとは別に、2つの方法で反対の熱心な読み込みを制御できます。
Include
ステートメントの使用:
db.Suppliers.Include(s => s.Services)
投影にナビゲーションプロパティを含める:
from supp in db.Supliers
from serv in supp.Services
select new { supp.Name, serv.ServiceName }
(もっと多くの方法がありますが、これらは最も重要な方法です)
これは、サービスまたはリポジトリでのlinqクエリの記述に適用されます。IQueryable
他の人が言っているように:あなたのサービス/リポジトリメソッドの消費者に公開しないでください。
最後の重要な注意事項:遅延読み込みは、ライフコンテキストの範囲内でのみ可能です。コンテキストが破棄され、遅延読み込みナビゲーションプロパティがアドレス指定されると、例外がスローされます。同時に、寿命の短いコンテキストインスタンスを使用することをお勧めします。したがって、ジレンマがあります。エンティティオブジェクトのみを公開するか、DTOのみを公開するか、モデルなどを表示します。遅延読み込みが有効なエンティティオブジェクトを公開すると、コンシューマーが、まだ読み込まれていないナビゲーションプロパティを誤ってアドレス指定し、コンテキストが失われる可能性があります。