我注意到MVC的项目模板在使用单个用户帐户时会在当前Owin上下文中放置一些对象(在App_Start/Startup.Auth.cs
中):
// Configure the db context, user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
看起来这是访问数据库中的Identity功能。我的理解是,每个请求创建一个ApplicationDbContext
实例,并通过整个管道重新使用。用我自己的实体框架DbContext
做同样的事情是否有益?
例如,我在App_Start/Startup.Data.cs
中创建了一个新文件:
public partial class Startup
{
public void ConfigureData(IAppBuilder app)
{
app.CreatePerOwinContext(CreateParkingEntities);
}
protected ParkingEntities CreateParkingEntities()
{
return new ParkingEntities();
}
}
然后在Startup.cs
:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
ConfigureData(app);
}
}
然后我可以在我的控制器中使用上下文:
private ParkingEntities _db;
public ParkingEntities DbContext
{
get
{
return _db ?? HttpContext.GetOwinContext().Get<ParkingEntities>();
}
private set
{
_db = value;
}
}
我认为如果这是标准做法,实体框架会有一些脚手架,但它只是在控制器级别创建一个实例。是否可以安全地假设如果DbContext
仅从该控制器访问,那么它在功能上等同于上述实现并将其置于Owin管道中是否过度了?
我认为如果需要额外的设置,这种方法的另一种用法是DbContext的单个初始化点。
答案 0 :(得分:0)
使用EF db-context的主要方法很简单:连接到db-context,获取数据并忘记这个db-context对象。 EF上下文是IDisposable并在dispose之后关闭连接(不要忘记使用(){})。这意味着,当您需要数据库连接时,可以在应用程序的任何位置创建EF数据上下文。您可以在控制器操作中创建新的db-context,如果他们正在使用您的数据库。一切都取决于您的应用程序的架构。如果您确定,对您的应用程序的所有请求都需要许多db操作,我认为您的每个owin-context的db-context解决方案都很有用。
答案 1 :(得分:0)
DbContext
旨在实现轻量级,因此每次需要时都不会花费太多成本来创建新实例。主要成本是重新创建连接和垃圾收集您正在创建的所有实例。
请注意,如果您在DbSets上使用Find()
方法,它将缓存结果,因此下次您要求时,它不需要转到数据库。如果重新使用相同的上下文,则可以利用该缓存,但如果创建新上下文,则会丢失缓存。
如果将DbContext
存储在控制器的实例成员中,那么它将仅用于一个请求,因为将为每个请求创建一个新的控制器实例。只要确保你不要把它放在静态成员中 - 我希望如果你这样做,你会得到各种各样的竞争条件。