36

メソッド呼び出しのために 2 つの DbContext がネストされている次のケースでは、次のようになります。

public void Method_A() {
    using (var db = new SomeDbContext()) {
        //...do some work here
        Method_B();
        //...do some more work here
    }
}

public void Method_B() {
    using (var db = new SomeDbContext()) {
        //...do some work
    }
}

質問:

  1. この入れ子は何か問題を引き起こしますか? (そして、正しい DbContext は正しい時間に破棄されますか?)

  2. Method_A を次のようにリファクタリングする必要がある場合、このネスティングは悪い習慣と見なされますか?

    public void Method_A() {
        using (var db = new SomeDbContext()) {
            //...do some work here
        }
    
        Method_B();
    
        using (var db = new SomeDbContext()) {
            //...do some more work here
        }
    }
    

ありがとう。

4

4 に答える 4

42

ここDbContextでは、派生クラスが実際に少なくとも 3 つのことを管理しています。

  • データベースとエンティティ モデルを記述するメタデータ
  • 基礎となるデータベース接続、および
  • 変更の追跡、関係の修正などのために、コンテキストを使用して読み込まれたエンティティのクライアント側の「キャッシュ」。 EFs 機能. 該当する場合、アプリケーションでの適切なキャッシュの代わりにはなりません)。

Entity Framework は通常、メタデータ (項目 1) をキャッシュして、すべてのコンテキスト インスタンス (または、少なくとも同じ接続文字列を使用するすべてのインスタンス) で共有されるようにします。したがって、ここでは心配する必要はありません。

他のコメントで述べたように、コードは 2 つのデータベース接続を使用することになります。これは、問題になる場合とそうでない場合があります。

また、クライアント キャッシュが 2 つになります (項目 3)。外側のコンテキストからエンティティをロードした場合、再び内側のコンテキストから、メモリ内にエンティティの 2 つのコピーが作成されます。これは間違いなく混乱を招き、微妙なバグにつながる可能性があります。つまり、共有コンテキスト オブジェクトを使用したくない場合は、オプション 2 の方がオプション 1 よりも優れている可能性があります。

transactionsを使用している場合は、さらに考慮事項があります。複数のデータベース接続があると、トランザクションが分散トランザクションに昇格する可能性がありますが、これはおそらく望ましくありません。db トランザクションについて言及していないので、ここではこれ以上説明しません。

それで、これはあなたをどこに残しますか?

このパターンを単にDbContextコード内でのオブジェクトの受け渡しを避けるために使用している場合は、コンテキストをパラメーターとして受け取るようにリファクタリングする方がよいでしょうMethodB。寿命の長いコンテキスト オブジェクトをどのようにすべきかという問題は、繰り返し出てきます。経験則として、単一のデータベース操作または関連する一連のデータベース操作に対して新しいコンテキストを作成します。(たとえば、このブログ投稿この質問を参照してください。)

DbContext(別の方法として、既存の接続を受け取る派生クラスにコンストラクターを追加することもできます。その後、複数のコンテキスト間で同じ接続を共有できます。)

便利なパターンの 1 つは、コンテキスト オブジェクトを作成し、それをプライベート フィールドまたはプロパティとして格納する独自のクラスを作成することです。次に、クラスを実装IDisposableし、そのDispose()メソッドがコンテキスト オブジェクトを破棄します。呼び出しコードは、クラスのインスタンスを通知し、コンテキストや接続についてまったく心配する必要はありません。

複数のコンテキストを同時にアクティブにする必要があるのはいつですか?

これは、マルチスレッドのコードを記述する必要がある場合に役立ちます。データベース接続はスレッド セーフではないため、一度に 1 つのスレッドからのみ接続 (したがって EF コンテキスト) にアクセスする必要があります。制限が厳しすぎる場合は、スレッドごとに 1 つずつ、複数の接続 (およびコンテキスト) が必要です。これは面白いと思うかもしれません。

于 2013-01-29T13:45:12.700 に答える
1

Method_B にコンテキストを渡すことで、コードを変更できます。そうする場合、2 番目の db 呼び出し SomeDbContext の作成は必要ありません。

このリンクのstackoverflowに質問があります datacontext の「Using」ステートメントの適切な使用

于 2013-01-28T22:52:13.627 に答える
0

データベースへの接続数、および新しい接続を開く必要がある回数の影響を考えると、重要な問題ではなく、アプリケーションを最高のパフォーマンスで実行するためのサポートに制限がない場合、すべて問題ありません。あなたのコードはうまくいきます。db コンテキストのみを作成してもパフォーマンスへの影響は少ないため、最初の読み込み後にメタデータがキャッシュされ、コードがクエリを実行する必要があるときにデータベースへの接続が発生します。わずかなパフォーマンスの考慮とコード設計により、コンテキスト ファクトリを作成して、アプリケーションのインスタンスごとに各 Db コンテキストのインスタンスを作成することをお勧めします。

パフォーマンスに関するその他の考慮事項については、このリンクを 参照してください http://msdn.microsoft.com/en-us/data/hh949853

于 2013-01-27T09:52:19.730 に答える