Entity FrameworkはAspにあります.NetMVCでの実装One Context Per Request(付源コード)
6091 ワード
前編「Entity FrameworkのIdentity mapおよびUnit of Workモード」では、EFのIdentity mapとUnit of Workモードのため、EFは以下の特性を体現している.
≪一意性|Uniqueness|emdw≫:1つのContextのライフサイクルで、1つのEntityには1つのインスタンスしかありません.このインスタンスに対する変更は、データベースに保存されていなくても、Contextのライフサイクル全体に影響します.
トランザクション:Entityに対するすべての変更は、SaveChangeメソッドが呼び出されたときにデータベースに一緒に保存され、最終的に永続化されます.
以下、EFの上記の特徴に基づいて、MVCでOne Context Per Requestを実現する必要がある理由を分析する.すなわち、1つのRequestライフサイクルの中で、1つのContextだけがある.
目次を読む:
一、毎回Contextを作成する欠点
二、グローバルContextの使用の欠点
三、MVCでOne Context Per Requestを実現する
四、AutofacによるOne Context Per Requestの実現
一、毎回Contextを作成する欠点
まず、データ処理のたびにnew contextを使用すると、より多くのリソースオーバーヘッドが発生します. ビジネスロジック層がGetStudioメソッドを呼び出してデータを取得した後、Studioのナビゲーション属性Schoolにアクセスするにはどうすればいいですか?論理層コードがナビゲーションを使用する場合、EFはcontextライフサイクル中にのみデータベースを再要求し、ナビゲーション属性Schoolのデータを取得することができるため、異常が発生します. 挿入操作であり、かつ複数の関連テーブルのデータ挿入であれば、挿入操作が異なるcontextで完了すると、EFのトランザクション効果は適用されません.データの同時挿入に成功することを保証し、失敗したら一緒にロールバックします. ループにデータを挿入すると、データを挿入するたびに異なるcontextで完了し、パフォーマンスは悲劇です.
二、グローバルContextを使用する欠点
グローバルにContextを使用すると、ローカルにキャッシュされるデータが増え、プログラムの使用時間が長くなるにつれて、消費されるリソースが大きくなります. グローバルContextを使用すると、キャッシュデータがタイムリーに更新されなくなります.データベース内のデータが変更されても,EFを用いて取り出されたデータは変更前のデータである可能性がある.
したがって、 MVCプロジェクトではrequestごとにContext を使用することを推奨します. Winform中和WPFにおいて、1つのFormまたは1つのPresenter 1つのContext WebService,Web APIでは、呼び出すたびにContextを1つ使用する.
三、MVCでOne Context Per Requestを実現する
≪一意性|Uniqueness|emdw≫:1つのContextのライフサイクルで、1つのEntityには1つのインスタンスしかありません.このインスタンスに対する変更は、データベースに保存されていなくても、Contextのライフサイクル全体に影響します.
トランザクション:Entityに対するすべての変更は、SaveChangeメソッドが呼び出されたときにデータベースに一緒に保存され、最終的に永続化されます.
以下、EFの上記の特徴に基づいて、MVCでOne Context Per Requestを実現する必要がある理由を分析する.すなわち、1つのRequestライフサイクルの中で、1つのContextだけがある.
目次を読む:
一、毎回Contextを作成する欠点
二、グローバルContextの使用の欠点
三、MVCでOne Context Per Requestを実現する
四、AutofacによるOne Context Per Requestの実現
一、毎回Contextを作成する欠点
一般に、プロジェクトのデータ・アクセス・レイヤでEntity Frameworkを使用します.コードは次のとおりです.public IEnumerable<Student> GetStudents()
{
using (var context = new SchoolContext())
{
return context.Students.ToList();
}
}
これはデータ・アクセス・レイヤで非常に一般的な方法であり、DB内のすべてのStudioデータを返します.
ここでContextを使用する場合は、Contextのインスタンスを作成して操作します.
しかし、この方法は以下の欠点をもたらしました.
public IEnumerable<Student> GetStudents()
{
using (var context = new SchoolContext())
{
return context.Students.ToList();
}
}
二、グローバルContextを使用する欠点
「Contextを作成するたびに」という欠点が見られ、グローバルContextを使用するのが良い解決策だと思われるかもしれません.
しかし、グローバルContextがもたらす問題はもっと大きい.
したがって、
三、MVCでOne Context Per Requestを実現する
考えはこうですGlobalではasax.csファイルでは、Begin RequestイベントでContextを作成および保存します.End RequestイベントでContextを破棄する.さらに、このContextを取得するために、開示された静的属性が提供される.
詳細なコードは次のとおりです.
Globalでasax.cs中protected virtual void Application_BeginRequest()
{
HttpContext.Current.Items["_EntityContext"] = new EntityContext();
}
protected virtual void Application_EndRequest()
{
var entityContext = HttpContext.Current.Items["_EntityContext"] as EntityContext;
if (entityContext != null)
entityContext.Dispose();
}
静的属性を追加し、プログラム内でContextの取り出しと使用を容易にするpublic class EntityContext
{
public static EntityContext Current
{
get { return HttpContext.Current.Items["_EntityContext"] as EntityContext; }
}
}
四、AutofacによるOne Context Per Requestの実現
Autofacはい.NetのIoc容器、具体的な使い方は、ここIoC容器Autofac(4)-Autofact+Asp.NetMVC+EF Code First(ソースコード付)
本文のDemoソースは、上のブログに添付されているソースコードを元に修正したものです.
ここでは、Autofacを使用してContextを登録する方法について説明します.
アプリケーション_Start関数内で、次のコードを実行します.var builder = new ContainerBuilder(); // builder
// builder, one context per request
builder.RegisterType<eassistdevContext>().InstancePerHttpRequest();
var container = builder.Build();//
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));// MVC Controller , Auotfac
より詳細な手順では、ここでソースコードAutofactMVC(One-Context-Per-Request).zipを直接ダウンロードできます.
ソースコードにもMiniProflerが使われていますので、お勧めします
protected virtual void Application_BeginRequest()
{
HttpContext.Current.Items["_EntityContext"] = new EntityContext();
}
protected virtual void Application_EndRequest()
{
var entityContext = HttpContext.Current.Items["_EntityContext"] as EntityContext;
if (entityContext != null)
entityContext.Dispose();
}
public class EntityContext
{
public static EntityContext Current
{
get { return HttpContext.Current.Items["_EntityContext"] as EntityContext; }
}
}
Autofacはい.NetのIoc容器、具体的な使い方は、ここIoC容器Autofac(4)-Autofact+Asp.NetMVC+EF Code First(ソースコード付)
本文のDemoソースは、上のブログに添付されているソースコードを元に修正したものです.
ここでは、Autofacを使用してContextを登録する方法について説明します.
アプリケーション_Start関数内で、次のコードを実行します.
var builder = new ContainerBuilder(); // builder
// builder, one context per request
builder.RegisterType<eassistdevContext>().InstancePerHttpRequest();
var container = builder.Build();//
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));// MVC Controller , Auotfac
より詳細な手順では、ここでソースコードAutofactMVC(One-Context-Per-Request).zipを直接ダウンロードできます.
ソースコードにもMiniProflerが使われていますので、お勧めします