我可以在dbContext中使用Async / Await吗?如果是这样,我什么时候应该使用ConfigureAwait(false)?

时间:2016-10-23 00:18:57

标签: c# .net multithreading entity-framework asynchronous

说我有以下代码段:

using (var db = new dbContext()){
     var user = db.Users.Find(3);
     user.Name = "newName";
     var viewModel = GetViewModelAndDoStuffToUser(user);
     db.SaveChanges();
     return viewmodel;
}

现在我正在尝试通过利用async / await来大规模提高此代码段的性能,但我已经读过dbContext不是“线程安全的”。所以我有点困惑:

  1. 我是否可以将async/await用于与dbContext相关的调用
  2. 当我这样做时是否应该使用.ConfigureAwait(false)。我已经读到这告诉我们不要重新进入MVC和WebApi控制器所需的“.NET上下文” - 但这是为这些控制器提供服务的应用程序的服务层。我还读到使用它可以防止死锁。
  3. 是否 - 在更复杂的情况下 - 我可以使用dbContext
  4. 使用相同的Task.WhenAll()实例并行化调用

    以下代码段是否是正确方向的可扩展,线程安全的步骤?

    using (var db = new dbContext()){
         var user = await db.Users.FindAsync(3).ConfigureAwait(false);
         user.Name = "newName";
         var viewModel = await GetViewModelAndDoStuffToUserAsync(user).ConfigureAwait(false);
         await db.SaveChangesAsync().ConfigureAwait(false);
         return viewmodel;
    }
    

1 个答案:

答案 0 :(得分:3)

简短回答是"是","是","是"。

很长的答案是虽然db上下文不是线程安全的,但async / await构造仍然没有将db上下文传递给其他线程,所以你在这里很安全。

ConfigureAwait(false)的调用而言,除了UI代码之外,你应该在任何地方都这样做。由于数据库代码很少放在UI层中(它永远不会放在UI级别的高质量生产代码中),因此您应该在后端进行的每个异步调用中使用ConfigureAwait(false)

最后,如果通过调用db context的async方法创建多个任务,则可以创建协同例程。它们并行化系统外的工作(例如,进行并发数据库调用),但最终它们并不是同时运行的。这样可以保护您的数据库上下文安全,因为对它的任何更改都是按顺序应用的。