3

いくつかのコードを渡されました。コントローラー クラスには、初期化されたデータベース コンテキストを保持するプロパティがあります。

public class MyController: Controller
{
    protected AssetManagerContext db = new AssetManagerContext("ConnectionString");
    // Actions...etc.

    [HttpGet]
    public ActionResult Edit(int id)
    {
        MyAsset myAsset = db.Assets.Find(id); // Used and not disposed
        return View(myAsset);
    }
 }

ほとんどのアクションは、このコンテキストを破棄せずに使用します。私の懸念は、コンテキストが開いたままになっていることです。

  1. このコンテキストが明示的に閉じられていないことを心配する必要がありますか (.Dispose() または using {} ステートメントによって)

  2. 変数はクラスの一部であり、アクション全体で使用されるため、心配する必要がある場合、この状況をどのように処理すればよいでしょうか?

4

4 に答える 4

6

Controller クラスには、dispose のメソッドがあります。したがって、コントローラーでそのメソッドをオーバーライドし、そのコンテキストを破棄します。

protected override void Dispose(bool disposing)
{
   base.Dispose(disposing);
   db.Dispose();
}

コンテキストが完了すると、自動的に呼び出されます。

于 2012-08-23T16:57:26.270 に答える
4

コントローラーへの呼び出しの間にコンテキストを開いたままにしておくことは、決して良い考えではありません。

これにより、MyController インスタンスが GC によって破棄されるまで、DB 接続が保持されます。

コントローラーが Entity Framework とのすべてのやり取りを行う場合 (ビューでドメイン オブジェクトを遅延ロードする必要がない場合)、最も単純なパターンは次のとおりです。

public class MyController : Controller
{
    public ActionResult MyAction(...)
    {
        using (AssetManagerContext db = new AssetManagerContext("ConnectionString"))
        {
            // Do stuff
        }
    }
}

ビューがコンテキストからオブジェクトを遅延ロードする必要がある場合は、実際にコンテキスト オブジェクトへの参照をクラスのプロパティとして保持し、@Kundan の提案に従って IDisposable を実装できます。

于 2012-08-23T16:55:41.697 に答える
2

実際には、それはあまり重要ではありません。Stephen Walterがコメントに彼のブログ エントリの 1 つへのリンクを投稿したときに指摘したように、データ コンテキストをクリーンアップすることは特に重要ではありません。最終的に、データ コンテキストは独自の接続を管理し、接続をプールするという素晴らしい仕事をするからです。

クリーンアップしないと、必要以上に余分なメモリが割り当てられる可能性がありますが、接続を必要以上に長く開いたままにすることはありません。

ただし、ベスト プラクティスは、自分でクリーンアップすることです。それが(現在)問題ではないことを知っていても。

于 2012-08-23T17:23:37.243 に答える
0

まず、データベース接続、ストリームなどの高価なリソースを常に明示的に解放する必要があります。これを行うためにフレームワークに依存しないでください。現在これを行っていても、Microsoft が将来これを変更するかどうかはわかりません。おそらく見つけられないほどの大きなリークが残ります。

ブロックを使用して、すべてのアクションでコンテキストを作成および破棄できますusing

しかし、いくつかのコードを省いてDRYOnActionExecuting原則に従うために、 and をOnActionExecutedContextそれぞれオーバーライドすることで、すべてのアクションの前後にコンテキストをインスタンス化して破棄することができます。

public class MyController: Controller
{
    protected AssetManagerContext db;

    [HttpGet]
    public ActionResult Edit(int id)
    {
        MyAsset myAsset = db.Assets.Find(id); // Used and not disposed
        return View(myAsset);
    }

    protected override void OnActionExecuting(ActionExecutingContext db) {
        base.OnActionExecuting(db);
        db = new AssetManagerContext("ConnectionString");
    }

    protected override void OnActionExecuted(ActionExecutedContext db) {
        base.OnActionExecuted(db);
        db.Dispose();
    }
}
于 2012-08-23T16:59:25.113 に答える