Entity Framework-“ Entities”をインスタンス化する方法対象
-
05-07-2019 - |
質問
私はEntity FrameworkとASP.Net MVCの初心者であり、どちらも深く理解していなくてもほとんどチュートリアルから学んでいます。 (.Net 2.0、ADO.Net、WebFormsの経験があります)
現在の疑問は、エンティティオブジェクトをインスタンス化する方法にあります。
基本的にはコントローラーでこれを行っています:
public class PostsController : Controller {
private NorthWindEntities db = new NorthWindEntities();
public ActionResult Index() {
// Use the db object here, never explicitly Close/Dispose it
}
}
このようにしているのは、MSDNブログでそれが正しい方法だと思ったほどに権威があるように思えたからです。
しかし、私はこれについてかなり不安を感じています。たくさんのコードを節約できますが、私は慣れています:
using (NorthWindEntities db = new NorthWindEntities() {
}
接続を必要とするすべてのメソッドで、そのメソッドが必要とする他のメソッドを呼び出す場合、dbをパラメーターとして渡します。これが、Linq-to-SQLが存在する前に、接続オブジェクトですべてを行った方法です。
私を不安にさせているもう1つの点は、NorthWindEntitiesがIDisposableを実装していることです。これは慣例により、Dispose()メソッドを呼び出す必要がありますが、そうではありません。
これについてどう思いますか?
エンティティオブジェクトをインスタンス化するのは正しいですか?クエリごとに接続を開いたり閉じたりして、接続を処理する必要がありますか?
または、using()句を使用して明示的に破棄する必要がありますか?
ありがとう!
解決
コントローラー自体はIDisposableを実装します。そのため、Disposeをオーバーライドして、コントローラーのインスタンス化時に初期化するもの(オブジェクトコンテキストなど)を破棄できます。
コントローラーは、単一の要求の間のみ有効です。したがって、アクション内でusingを使用し、コントローラー全体に対して1つのオブジェクトコンテキストを使用することは、コンテキストの数とまったく同じです。
これら2つのメソッドの大きな違いは、ビューがレンダリングされる前にアクションが完了することです。したがって、アクション内のusingステートメントでObjectContextを作成すると、ビューがレンダリングされる前にObjectContextが破棄されます。そのため、アクションが完了する前に必要なコンテキストから何かを読んでおく方がよいでしょう。ビューに渡すモデルがIQueryableのような遅延リストである場合、ビューがレンダリングされる前にコンテキストを破棄するため、ビューがIQueryableを列挙しようとすると例外が発生します。
対照的に、コントローラーの初期化時にObjectContextを初期化する(または、アクションの実行時に初期化される遅延初期化コードを記述して)Controller.DisposeのObjectContextを破棄する場合、コンテキストは引き続きビューがレンダリングされるとき。この場合、IQueryableをビューに渡すことは安全です。コントローラは、ビューがレンダリングされた直後に破棄されます。
最後に、ControllerにEntity Frameworkを認識させるのはおそらく悪い考えだと指摘していなければ、私は失望します。モデルとリポジトリパターンに別のアセンブリを使用して、コントローラーがモデルと通信できるようにします。これについては、Google検索でかなり検索されます。
他のヒント
ここであなたは良い点を挙げています。 ObjectContextの有効期間はどのくらいですか?すべてのパターンと実践の本(Dino Espositoの Microsoft-NET-Architecting-Applications )は、DataContextを長く存続させたり、キャッシュしたりしてはならないことを示しています。
あなたの場合、すべてのコントローラーに対してObjectContextが1回開始されるControllerBaseクラス(MVCの実装を知らないので、我慢してください)がないのはなぜだろうと思っていました。特に、Entity Frameworkによって既に実装されているアイデンティティマップパターンについて考えてください。 PostsControllerとして別のコントローラーを呼び出す必要がある場合でも、同じコンテキストで機能し、パフォーマンスも向上します。