2

Microsoft チュートリアルhttp://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp -net-mvc-applicationは、次のように破棄パターンを実装するようにアドバイスします。

private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    context.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

なぜ私はそれをしなければならないのか、なぜ私は単に文脈を処分することができないのか、そして私だけを使うとどうなるか:

context.Dispose()

Microsoft の破棄パターンの実装の目標はどれですか?

4

2 に答える 2

5

あなたはただ使うことができます...

    public void Dispose() // IDisposable implementation
    {
        context.Dispose();
    }

...仮想Dispose過負荷なし、プライベートdisposedフラグなし

  • Disposeコンテキスト自体が既に呼び出されているかどうかをチェックするため、2 回目の呼び出しでは何も起こらず、例外はスローされません。
  • Disposeコンテキスト クラスには独自のファイナライザーがあり、明示的に呼び出さなかった場合にガベージ コレクションでデータベース接続が確実に解放されます。

最後のポイントは、まったく呼び出す必要がないという意味ではありませんcontext.Dispose()。ガベージ コレクターがコンテキストをファイナライズする時点は不確定であり、新しいコンテキスト インスタンスを作成した時点よりも後になる可能性があるためです。おそらく同じエンティティで使用してください。これにより、問題が発生する可能性があります。そのため: 常に明示的に、またはusingブロックによってコンテキストを破棄します。

またGC.SuppressFinalize(this);、クラスにも基本クラスにもファイナライザーがないため、ここで効果があるとは思えないため、抑制するものは何もありません。

私の意見では、あなたの例のパターンはフラグメント (ファイナライザー/デストラクタの実装が欠落している) であり、クラス内の独自のアンマネージ リソースを処理する必要がある場合に役立つ可能性があります。しかし、あなたの UnitOfWork クラスでは、そうする必要はありません。アンマネージ リソース (データベース接続) はコンテキストによって管理され、 を呼び出して作業を委譲するだけで済みますcontext.Dispose()

于 2012-10-08T19:39:19.690 に答える
2

クライアントコードはリポジトリとのみ通信する必要があります。リポジトリは、実装の詳細(DBContext、EF、および使用しているバックエンドの使用など)を呼び出し元のコードから隠します。これは、リポジトリパターンの主な目的の1つです。

そのため、リポジトリへの呼び出しコードはcontext.disposeを呼び出すことができず、呼び出すべきではありません。文脈についてさえ知らないはずです。リポジトリについてのみ認識し、Disposeメソッドを呼び出します(明示的に、またはできればキーワードを使用して)

于 2012-10-07T21:02:39.713 に答える