18

私は Entity Framework に慣れようとしています。そのほとんどは単純明快に思えますが、Include メソッドを使用した熱心な読み込みとデフォルトの遅延読み込みの違いについて、私は少し混乱しています。どちらも関連エンティティをロードしているように見えるため、表面的には同じことをしているように見えます。私は何が欠けていますか?

4

4 に答える 4

30

1 対多の関係を持つ 2 つのエンティティがあるとします: Customer と Order で、各 Customer は複数の Order を持つことができます。

Customer エンティティを読み込む場合、Entity Framework を使用すると、Customer の Orders コレクションを熱心に読み込むか、遅延読み込みすることができます。Orders コレクションの一括読み込みを選択した場合、データベースから Customer を取得すると、Entity Framework は、1 つのクエリで Customer の情報と Customer の Orders の両方を取得する SQL を生成します。ただし、Orders コレクションの遅延ロードを選択した場合、データベースから Customer を取得すると、Entity Framework はCustomer の情報のみを取得する SQL を生成します (後で Customer の Orders コレクションにアクセスすると、Entity Framework は別の SQL ステートメントを生成します)。あなたのコードで)。

いつイーガー ロードを使用するか、いつレイジー ロードを使用するかを決定することは、取得したエンティティに対して何を期待するかにかかっています。顧客の情報のみが必要であることがわかっている場合は、Orders コレクションを遅延読み込みする必要があります (顧客の情報のみを取得することで SQL クエリが効率的になるようにします)。逆に、Customer の Orders をトラバースする必要があることがわかっている場合は、Orders をeager-load する必要があります (コードで Customer's Orders にアクセスすると、追加のデータベース ヒットを節約できます)。

PS 遅延読み込みを使用すると N+1 問題が発生する可能性があるため、十分に注意してください。たとえば、顧客とその注文のリストを表示するページがあるとします。ただし、注文を取得するときに遅延読み込みを使用することにしました。Customers コレクションを反復処理してから各 Customer の Orders を反復処理すると、各 Customer に対してデータベース ヒットが実行され、Orders コレクションに遅延ロードされます。これは、N 人の顧客の場合、熱心な読み込みを使用した場合に 1 つのデータベース ヒットだけではなく、N+1 のデータベース ヒット (すべての顧客をロードするために 1 つのデータベース ヒット、次にそれぞれの注文をロードするために N のデータベース ヒット) があることを意味します。 (これにより、すべての顧客とその注文が 1 つのクエリで取得されます)。

于 2010-08-17T17:33:55.387 に答える
17

SQL の世界から来た場合は、JOIN について考えてみてください。

グリッドに 10 件の注文と注文した顧客を表示する必要がある場合は、次の 2 つの選択肢があります。

1) 遅延読み込み (= 11 クエリ = 低速パフォーマンス)

EF は、注文を取得するためのクエリと、顧客データを取得するための各注文のクエリを実行します。

Select * from order where order=1
+
10 x (Select * from customer where id = (order.customerId))

1) EAGER LOAD (= 1 クエリ = 高いパフォーマンス)

EF は、JOIN を使用して注文と顧客を取得する単一のクエリを実行します。

Select * from orders INNER JOIN customers on orders.customerId=customer.Id where order=1

PS: データベースからオブジェクトを取得すると、コンテキストがアクティブな間、オブジェクトはキャッシュに格納されます。私が LAZY LOAD で作成した例では、10 件の注文すべてが同じ顧客に関連している場合、2 つのクエリしか表示されません。これは、オブジェクトを取得するように EF に要求すると、EF はオブジェクトがキャッシュにあるかどうか、およびそれがキャッシュにあるかどうかを確認するためです。 DB に対して別の SQL クエリを起動しないことがわかります。

于 2010-11-11T13:43:18.257 に答える
6

Eager ローディングは、ORM 固有のN+1 Selects問題を解決することを目的としています。短いバージョンは次のとおりです。いくつかのエンティティを直接取得する予定で、取得したエンティティを介して特定の関連エンティティにアクセスすることがわかっている場合は、すべての関連エンティティを 1 回のパスで事前に取得する方がはるかに効率的です。遅延読み込みを介して段階的に取得する場合と比較して。

于 2010-08-17T17:32:18.993 に答える