使用 async-await 进行数据库查询

Using async-await for database queries

我目前正在开发一个 ASP NET web api 项目,该项目以异步方式对数据库进行所有调用。

我们正在使用 ServiceStack.OrmLite,它为我们提供了异步和同步 API 来进行数据库调用。

我们正在做的例子:

选项 1

var activity = await context.SingleByIdAsync<Activity>(x => x.Id == myId);
var place = await context.SingleByIdAsync<Place>(x => x.Id == myId);

但我们也可以这样实现。

选项 2

var activity = context.SingleById<Activity>(x => x.Id == myId);
var place = context.SingleById<Place>(x => x.Id == myId);

根据我对异步编程的了解,选项 1 是阻塞线程并在操作完成时释放它。

我认为选项 1 的实施方式比选项 2 更昂贵。

Go into a blocking wait - Thread.Sleep, Task.Wait, etc. This means that you fire your database request on thread A and then enter a wait on that thread: the thread is allocated but is blocked and not usable for anything else. When your data is ready, you somehow learn of that and exit the wait and your code continues on thread A.

  1. 最好的方法是什么?

  2. 使用异步操作进行数据库调用有什么好处?

  3. 我们是否正确地实现了异步调用?

  4. 如果我将对数据库的所有调用都切换为同步,会不会有问题?

  1. 最好的方法是什么?

    这很难通过这么少的代码来判断,但一般来说,如果您愿意更改调用堆栈中的所有方法并且有合适的异步方法可用,请使用它。

    我所说的 更改调用堆栈中的所有方法 的意思是,如果您将方法 T A() 更改为异步(即 async Task<T> AAsync() 然后您还必须将任何调用 A 的方法也更改为异步的。

    我所说的 正确的异步方法 的意思:在 ASP.Net 的情况下,没有 UI-Thread 因此哪个线程将不重要被同步方法阻塞。因此,在这种情况下,合适的异步方法应该是执行一些异步 IO 并且不阻塞任何线程(甚至不阻塞某些线程池线程)的方法。

  2. 数据库调用使用异步操作有什么好处?

    总的来说,在 ASP.Net 中使用异步的好处是,当请求异步等待某些(适当的)异步操作完成时,它不会阻止任何线程处理另一个请求。

    因此,只要您使用的包将数据库调用实现为适当的异步 IO,您将受益于服务器更好的可扩展性(即它可以并行处理更多请求)。

  3. 我们是否正确地实现了异步调用?

    很难从这么少的代码中分辨出来,但只要你不在调用堆栈中使用 Task.Wait(),你可能正在使用它来更正。

  4. 如果我将对数据库的所有调用都切换为同步,会不会有问题?

    如 2. 中所述,当两个请求同时完成时,您可能会遇到问题。

你说“从我对异步编程的了解来看,选项1我们阻塞线程并在操作完成时释放线程。”,恰恰相反.当线程到达 await 时,它将 异步等待 等待的任务完成。这意味着线程将可以自由地做其他事情。完成或失败(有例外)的任务将安排继续执行。这取决于捕获的 synchronization context.

您还说过 “我认为选项 1 的实现方式比选项 2 更昂贵。”,这并没有错,因为异步方法内置于一个状态机,会有一点开销。但是由于您处于 ASP.Net 上下文中,您将极大地受益于使用异步操作来释放线程以处理其他请求。

Here 是一篇关于在 ASP.Net.

上使用异步的文章