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

SB2*_*055 7 .net c# multithreading asynchronous entity-framework

假设我有以下代码段:

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

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

  1. 我是否可以使用async/await与 dbContext 相关的调用
  2. 是否应该.ConfigureAwait(false)在我使用时使用。我读过这告诉我们不要重新输入 MVC 和 WebApi 控制器所需的“.NET 上下文”——但这是为这些控制器提供服务的应用程序的服务层。我还读到使用它可以防止死锁。
  3. 不管是不是-在更复杂的场景-我可以并行使用相同的实例调用dbContext使用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;
}
Run Code Online (Sandbox Code Playgroud)

das*_*ght 7

简短的回答是“是”、“是”和“是”。

长答案是,尽管 db 上下文不是线程安全的,但async/await构造无论如何都不会将 db 上下文传递给其他线程,因此您在这里是安全的。

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

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