什么时候应该创build一个新的DbContext()

我目前正在使用一个类似于这样的DbContext

 namespace Models { public class ContextDB: DbContext { public DbSet<User> Users { get; set; } public DbSet<UserRole> UserRoles { get; set; } public ContextDB() { } } } 

然后,我在所有需要访问数据库的控制器的顶部使用以下行。 我也使用它在我的UserRepository类,其中包含所有与用户有关的方法(如获得活跃的用户,检查他有什么angular色等):

 ContextDB _db = new ContextDB(); 

考虑这一点..有一个访客可以有多个DbContexts活跃的情况。 如果他访问使用UserRepository的控制器..这可能不是最好的想法,我有几个关于它的问题

  1. 我应该什么时候做一个新的DbContext /我应该有一个我传递的全局上下文吗?
  2. 我可以拥有一个全球范围内的环境吗?
  3. 这是否会导致性能下降?
  4. 其他人怎么做呢?

我使用一个基础控制器,公开派生控制器可以访问的DataBase属性。

 public abstract class BaseController : Controller { public BaseController() { Database = new DatabaseContext(); } protected DatabaseContext Database { get; set; } protected override void Dispose(bool disposing) { Database.Dispose(); base.Dispose(disposing); } } 

我的应用程序中的所有控制器都是从BaseController派生而来的,使用方法如下:

 public class UserController : BaseController { [HttpGet] public ActionResult Index() { return View(Database.Users.OrderBy(p => p.Name).ToList()); } } 

现在回答你的问题:

我应该什么时候做一个新的DbContext /我应该有一个我传递的全局上下文吗?

应根据请求创build上下文。 创build上下文,做你需要做的,然后摆脱它。 使用基类解决scheme,您只需要担心使用上下文。

不要尝试拥有全球性的环境(这不是Web应用程序的工作原理)。

我可以在所有地方使用一个全局上下文吗?

不,如果你保持一个上下文,它会跟踪所有的更新,添加,删除等,这将减慢你的应用程序,甚至可能会导致一些非常微妙的错误出现在您的应用程序。

您应该select将您的存储库您的上下文暴露给您的控制器,但不是两者。 有两个上下文从同一个方法访问,如果他们对应用程序的当前状态有不同的想法,就会导致错误。

就个人而言,我更愿意直接公开DbContext ,因为我看到的大多数存储库示例都只是简单地结束为DbContext简单包装。

这是否会导致性能下降?

第一次创build一个DbContext是非常昂贵的,但是一旦完成了这个过程,大量的信息被caching,以便后续的实例化更快。 与每次需要访问数据库时通过实例化一个上下文相比,您更有可能看到性能问题。

其他人怎么做呢?

这取决于。

有些人更喜欢使用dependency injection框架在创build时将其上下文的具体实例传递给其控制器。 这两个选项都很好。 我更适合小规模的应用程序,你知道正在使用的特定数据库是不会改变的。

有些人可能会说,你知道这一点,这就是为什么dependency injection方法更好,因为它使你的应用程序更具弹性改变。 我的意见是,它可能不会改变(SQL服务器和entity framework是难以掩盖的),我的时间最好写在我的应用程序特定的代码。

现在我正在尝试这种方法,它可以避免在调用不使用它的操作时实例化上下文。

 public abstract class BaseController : Controller { public BaseController() { } private DatabaseContext _database; protected DatabaseContext Database { get { if (_database == null) _database = new DatabaseContext(); return _database; } } protected override void Dispose(bool disposing) { if (_database != null) _database.Dispose(); base.Dispose(disposing); } } 

这显然是一个老问题,但如果你使用DI,你可以做这样的事情,并在请求的整个生命周期范围内的所有对象

  public class UnitOfWorkAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { var context = IoC.CurrentNestedContainer.GetInstance<DatabaseContext>(); context.BeginTransaction(); } public override void OnActionExecuted(HttpActionExecutedContext actionContext) { var context = IoC.CurrentNestedContainer.GetInstance<DatabaseContext>(); context.CloseTransaction(actionContext.Exception); } }