gpt4 book ai didi

c# - DBContext 中的 await 和 LINQ

转载 作者:行者123 更新时间:2023-11-30 21:55:35 25 4
gpt4 key购买 nike

我们的应用程序中有一个服务层,它由三个逻辑层组成 - Web 服务、业务模型服务(我们对执行业务逻辑和协调对各种存储库的调用的层的名称),以及连接到使用 EF6 的各种数据库。

我们的许多存储库调用只是通过 ToListAsync、FirstOrDefaultAsync 直接从数据库集中获取数据,如下所示:

public async Task<MyObject> GetSomeData()
{
using(var context = new myDBContext())
{
return await context.SomeDbSet.FirstOrDefault(o=>o.Something == true);
}
}

关于在这里使用 await 是否正确,我们有一些内部争论,因为在 await 之后此方法中没有任何执行。我/我们理解代码的编写方式,这是必要的,否则一旦方法存在,上下文就会被处理掉,这将导致异常。但是如果我们在这里等待,我们必须一直等待我们的调用堆栈向上(或向下,取决于您如何看待它),这将导致许多昂贵且有些不必要的上下文切换。

这里的另一个选项是使存储库方法同步,并在调用存储库方法的方法中执行 Task.Run(),例如:

Task.Run(() => MyRepository.GetSomeData());

如果需要,我们可以等待这个调用,或者再次将任务对象返回给调用者。这里的缺点是对数据库的调用然后变为同步,并且池中的一个线程在整个数据库调用期间处于阻塞状态。

所以这归结为什么更贵?通过 await 或让线程阻塞进行不必要的上下文切换?似乎没有正确答案,但是否有最佳实践?

如有任何想法,我们将不胜感激。

最佳答案

当然,您应该使用异步版本。

如您所说,如果您不使用 await,您将在操作完成之前处理上下文,但这并不意味着调用方法也需要使用 async-await。他们可以像您在 Task.Run 选项中提到的那样返回任务:

public Task<MyObject> FooAsync()
{
// do some stuff

return GetSomeDataAsync();
}

public async Task<MyObject> GetSomeDataAsync()
{
using(var context = new myDBContext())
{
return await context.SomeDbSet.FirstOrDefault(o=>o.Something == true);
}
}

您提到这种情况下的成本是一些昂贵的上下文切换。我不确定你的意思,但如果你指的是线程上下文切换,那么只有一个。调用线程将在等待异步操作时被释放,另一个线程将在该操作完成时继续运行。

不仅与执行实际操作所花费的时间相比,这可以忽略不计,如果您使用 Task.Run,当阻塞的线程从 CPU 中取出时,您将拥有相同的上下文切换.

在同步操作上使用 Task.Run 是多余的。它只是阻塞一个线程,并且它可能需要比异步等价物更多的上下文切换。

关于c# - DBContext 中的 await 和 LINQ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32193000/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com