Entity Framework MVC 中每个请求使用 Owin DbContext

Entity Framework with Owin DbContext per request in MVC

我注意到 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);

看起来这是访问数据库以获取身份特征。我的理解是 ApplicationDbContext 的单个实例是根据请求创建的,并在整个管道中重复使用。对我自己的 entity framework 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;
    }
}

我想如果这是标准做法,entity framework 会为此提供一些脚手架,但它只是在控制器级别创建一个实例。是否可以安全地假设如果 DbContext 仅从该控制器访问,那么它在功能上等同于上述实现并将其放在 Owin 管道中是否过大?

我想这种方法的另一个用途是 DbContext 的单一初始化点,如果需要额外的设置的话。

使用 EF db-context 的主要方法很简单:连接到 db-context,获取数据并忘记此 db-context 对象。 EF 上下文是 IDisposable 并在处理后关闭连接(不要忘记使用(){})。这意味着,当需要数据库连接时,您可以在应用程序的任何位置创建 EF 数据上下文。如果他们正在使用您的数据库,您可以在控制器操作中创建新的数据库上下文。一切都取决于您的应用程序的架构。如果您确定对您的应用程序的所有请求都需要许多数据库操作,我认为您的每个 owin-context 的 db-context 解决方案会很有用。

DbContext 设计为轻量级,因此每次需要时创建一个新实例的成本并不高。主要成本是重新创建连接和垃圾收集您正在创建的所有实例。

请注意,如果您在DbSets 上使用Find() 方法,它会缓存结果,所以下次您请求它时,不需要去数据库。如果您重复使用相同的上下文,则可以利用该缓存,但如果您创建新的上下文,则会丢失缓存。

如果您将 DbContext 存储在控制器的实例成员中,那么它只会用于一个请求,因为将为每个请求创建一个新的控制器实例。只要确保你不把它放在一个静态成员中——我希望你这样做会遇到各种竞争条件。