2

エンティティ フレームワーク 4.0 で予期しない動作が発生しています。誰かがこれを理解するのを手伝ってくれることを願っています。この質問のためにノースウィンド データベースを使用しています。また、デフォルトのコード ジェネレーターも使用しています (poco やセルフ トラッキングではありません)。フレームワークのコンテキストをクエリして、それらのオブジェクトをまだフェッチしていない場合にのみ往復することを期待しています。遅延読み込みをオフにすると、この動作が発生します。現在、私のアプリケーションでは、遅延読み込みを簡単にオンにしてからオフにして、目的の動作を得ることができます。それはかなりひどいので、助けてください。これは私の問題を示す良いコード例です。

Public Sub ManyRoundTrips()
    context.ContextOptions.LazyLoadingEnabled = True
    Dim employees As List(Of Employee) = context.Employees.Execute(System.Data.Objects.MergeOption.AppendOnly).ToList()

    'makes unnessesary round trip to the database, I just loaded the employees'
    MessageBox.Show(context.Employees.Where(Function(x) x.EmployeeID < 10).ToList().Count)
    context.Orders.Execute(System.Data.Objects.MergeOption.AppendOnly)
    For Each emp As Employee In employees
        'makes unnessesary trip to database every time despite orders being pre loaded.'
        Dim i As Integer = emp.Orders.Count
    Next
End Sub

Public Sub OneRoundTrip()
    context.ContextOptions.LazyLoadingEnabled = True
    Dim employees As List(Of Employee) = context.Employees.Include("Orders").Execute(System.Data.Objects.MergeOption.AppendOnly).ToList()

    MessageBox.Show(employees.Where(Function(x) x.EmployeeID < 10).ToList().Count)

    For Each emp As Employee In employees
        Dim i As Integer = emp.Orders.Count
    Next
End Sub

コードの最初のブロックが不要な往復を行うのはなぜですか?

4

2 に答える 2

3

あなたの期待は正しくありません。クエリは常にDB をクエリします。いつも。これは、LINQ が常に SQL に変換されるためです。

オブジェクトが既にフェッチされている場合はコンテキストから、そうでない場合は DB からオブジェクトをロードするには、ObjectContext.GetObjectByKey()を使用します。

于 2010-04-27T21:16:47.417 に答える
2

最初の「不要な」トリップが必要です。新しいクエリを実行したため、その間にデータベースが変更された可能性があります。代わりに employees 変数 (クエリの結果を保存した場所) を使用した場合、データベースにアクセスする必要はありません。

2 つ目は、各従業員の注文をフェッチするように要求しているため、必要です。遅延読み込みで、Include() がない場合、emp.Orders.Count() で要求するまで、注文は読み取られません。

クエリの反復処理を開始するまで (または反復処理が必要なメソッドを呼び出すまで)、LINQ to EF は何もしないことに注意してください。そのクエリを変数に保存してから .Count() を呼び出すと、往復が発生します。同じクエリを使用して列挙を開始すると、別の往復が発生します。そのクエリ内のエンティティ自体に関係があり、アクセスするたびに遅延読み込みがオンになっている場合、さらに別のラウンド トリップが発生します。

2 番目の例は、 Orders が必要であることを事前に知っている場合に、これを正しく行う方法を示しています。これは、熱心な読み込みです。コンテキストに戻って従業員を再度要求するのではなく、既にロードしたコンテキストを再利用することに注意してください。

于 2010-04-29T19:52:42.903 に答える