.NET Core EF,何时避免异步数据库调用
.NET Core EF, when to avoid asynchronous database calls
我目前正在编写一个简单的 Web 应用程序,它使用 mssql 数据库来存储数据。现在,我尝试设置我的业务逻辑层,从而以最好的方式构建它。
目前,我的所有调用都是使用 Linq 进行的,实际上 none 其中是异步的。我对异步编程相当陌生,并且通常很想知道我应该为哪些查询使用异步调用。
据我所知,使用异步数据库调用是有意义的,因为它释放了我的主线程上的内存并且不会阻塞 UI。还有,异步调用可以运行并发,也就是说可以同时做更多的事务。
但是,考虑到我在我的上下文中异步添加多个实体,并使用 SaveChangesAsync()
方法来结束我的上下文。在我的上下文中使用多个 AddAsync()
方法不是多余的吗,因为 SaveChangesAsync()
无论如何都会 运行 一切异步?
最后,据我所读和所见,很多人更喜欢使用异步数据库调用。也就是说,与其说是例外,不如说是规则。
如果是这样,在什么情况下我会避免异步数据库调用,在我的业务逻辑层中添加异步调用时我应该遵守哪些一般规则?
MVC 中的异步是关于释放请求处理线程,以便它们可以响应其他请求。它不会使代码更快,实际上会稍微慢一些。当谈到线程时,很容易看出它正在做什么,因为它移交给了工作线程。异步方法完成后会发生什么取决于同步上下文。在大多数情况下,它将在工作线程上恢复。
所以使用 [thread#] 前缀:
[1] using(var context = new AppContext())
{
[1] var orders = await context.Orders
.Where(x => x.CustomerId == customerId)
.OrderBy(x => x.OrderDate)
.ToListAsync();
[2] foreach(var order in orders)
{
//...
}
}
await
/async
意味着 C# 将移交给工作线程来执行代码,在本例中移交给 EF 来查询订单。它为剩余的代码创建一个恢复点,一旦该操作结束,这些代码将被执行。同时,线程 #1 结束,MVC 可以使用它来响应其他请求。
考虑异步调用时应权衡执行操作所需的时间,以及创建恢复路径和恢复代码所需的 time/resources。当面对相对不频繁的大型、昂贵的操作时,异步调用最有用,这些操作可能会占用响应线程,否则这些线程可能会在发起者等待时为请求提供服务。对于快速、常见的操作,async
可以减慢速度。因此,作为一般规则,如果一个操作要花费超过一两秒的时间才能达到 运行,那么它非常适合 async
/await
。对于快速查询,我默认保持同步。
我目前正在编写一个简单的 Web 应用程序,它使用 mssql 数据库来存储数据。现在,我尝试设置我的业务逻辑层,从而以最好的方式构建它。
目前,我的所有调用都是使用 Linq 进行的,实际上 none 其中是异步的。我对异步编程相当陌生,并且通常很想知道我应该为哪些查询使用异步调用。
据我所知,使用异步数据库调用是有意义的,因为它释放了我的主线程上的内存并且不会阻塞 UI。还有,异步调用可以运行并发,也就是说可以同时做更多的事务。
但是,考虑到我在我的上下文中异步添加多个实体,并使用 SaveChangesAsync()
方法来结束我的上下文。在我的上下文中使用多个 AddAsync()
方法不是多余的吗,因为 SaveChangesAsync()
无论如何都会 运行 一切异步?
最后,据我所读和所见,很多人更喜欢使用异步数据库调用。也就是说,与其说是例外,不如说是规则。
如果是这样,在什么情况下我会避免异步数据库调用,在我的业务逻辑层中添加异步调用时我应该遵守哪些一般规则?
MVC 中的异步是关于释放请求处理线程,以便它们可以响应其他请求。它不会使代码更快,实际上会稍微慢一些。当谈到线程时,很容易看出它正在做什么,因为它移交给了工作线程。异步方法完成后会发生什么取决于同步上下文。在大多数情况下,它将在工作线程上恢复。
所以使用 [thread#] 前缀:
[1] using(var context = new AppContext())
{
[1] var orders = await context.Orders
.Where(x => x.CustomerId == customerId)
.OrderBy(x => x.OrderDate)
.ToListAsync();
[2] foreach(var order in orders)
{
//...
}
}
await
/async
意味着 C# 将移交给工作线程来执行代码,在本例中移交给 EF 来查询订单。它为剩余的代码创建一个恢复点,一旦该操作结束,这些代码将被执行。同时,线程 #1 结束,MVC 可以使用它来响应其他请求。
考虑异步调用时应权衡执行操作所需的时间,以及创建恢复路径和恢复代码所需的 time/resources。当面对相对不频繁的大型、昂贵的操作时,异步调用最有用,这些操作可能会占用响应线程,否则这些线程可能会在发起者等待时为请求提供服务。对于快速、常见的操作,async
可以减慢速度。因此,作为一般规则,如果一个操作要花费超过一两秒的时间才能达到 运行,那么它非常适合 async
/await
。对于快速查询,我默认保持同步。