物議を醸しましょう!
リクエスト全体を通してコンテキストを維持することが良いことであるという一般的な MVC + EF コンセンサスには、いくつかの理由で同意しません。
パフォーマンスの向上が
少ない 新しいデータベース コンテキストを作成するのにどれだけコストがかかるか知っていますか? うーん... " DataContextは軽量で、作成するのに費用がかかりません"それはMSDNからのものです
IoC を間違えると問題ないように見えます..実際に
使用するまで IoC コンテナーを設定してコンテキストを破棄する場合、それが間違っていると、本当に間違っていることになります。IoC コンテナーから作成された大規模なメモリ リークが、コンテキストを常に正しく処理しているとは限らないことを2 回確認しました。サーバーが通常のレベルの同時ユーザーの間に崩壊し始めるまで、設定が間違っていることに気付くことはありません。開発中は発生しないため、負荷テストを行ってください。
偶発的な遅延読み込み
最新の記事の IQueryable を返して、ホームページにリストできるようにします。ある日、別の誰かが、それぞれの記事の横にコメント数を表示するよう求められました。そのため、ビューに簡単なコードを追加して、コメント数を次のように表示します...
@foreach(var article in Model.Articles) {
<div>
<b>@article.Title</b> <span>@article.Comments.Count() comments</span>
</div>
}
見た目も良く、動作も良好です。しかし実際には、返されたデータにコメントが含まれていなかったため、ループ内の記事ごとに新しいデータベース呼び出しが行われます。SELECT N+1 発行。10 件の記事 = 11 件のデータベース呼び出し。さて、コードは間違っていますが、それは起こりやすい間違いです。
データ層でコンテキストをシャットダウンすることで、これを防ぐことができます。しかし、 article.Comments.Count() の NullReferenceException でコードが壊れることはありませんか? はい、そのため、データレイヤーを編集して、ビュー レイヤーに必要なデータを取得する必要があります。これが本来あるべき姿です。
コードのにおい
ビューからデータベースにアクセスするのは何か問題があります。IQueryable が実際にはデータベースにヒットしていないことはわかっているので、そのオブジェクトは忘れてください。データレイヤーを離れる前に、データベースがヒットしていることを確認してください。
それで答えは
あなたのコードは(私の意見では)このようにする必要があります
データ層:
public List<Article> GetArticles()
{
List<Article> model;
using (var context = new MyEntities())
{
//for an example I've assumed your "MyTable" is a table of news articles
model = (from mt in context.Articles
select mt).ToList();
//data in a List<T> so the database has been hit now and data is final
}
return model;
}
コントローラ:
public ActionResult Index()
{
var model = new HomeViewModel(); //class with the bits needed for you view
model.Articles = _dataservice.GetArticles(); //irrelevant how _dataService was intialised
return View(model);
}
これを実行してこれを理解したら、おそらく IoC コンテナーでコンテキストを処理する実験を開始できますが、それ以前ではありません。私の警告に頭を上げてください-私は2つの大規模な失敗を見ました:)
しかし、正直なところ、好きなことをしてください。プログラミングは楽しいものであり、好みの問題であるべきです。私はあなたに私のことを言っているだけです。ただし、何をするにしても、「クールな子供たちがやっている」という理由だけで、コントローラーごとまたはリクエストごとに IoC コンテキストの使用を開始しないでください。その利点を本当に気にかけ、それがどのように正しく行われるかを理解しているからです。