我注意到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的单个初始化点 .
2 回答
DbContext
设计为轻量级,因此每次需要时都不需要花费太多成本来创建新实例 . 主要成本是重新创建连接和垃圾收集您正在创建的所有实例 .请注意,如果在DbSets上使用
Find()
方法,它将缓存结果,因此下次要求时,它不需要转到数据库 . 如果重新使用相同的上下文,则可以利用该缓存,但如果创建新上下文,则会丢失缓存 .如果将
DbContext
存储在控制器的实例成员中,则它将仅用于一个请求,因为将为每个请求创建一个新的控制器实例 . 只要确保你不要把它放在静态成员中 - 我希望如果你这样做,你会得到各种竞争条件 .使用EF db-context的主要方法很简单:连接到db-context,获取数据并忘记这个db-context对象 . EF上下文是IDisposable并在dispose之后关闭连接(不要忘记使用(){}) . 这意味着,当您需要数据库连接时,可以在应用程序的任何位置创建EF数据上下文 . 您可以在控制器操作中创建新的db-context,如果他们正在使用您的数据库 . 一切都取决于您的应用程序的架构 . 如果您确定,对您的应用程序的所有请求都需要许多db操作,我认为您的每个owin-context的db-context解决方案都很有用 .