EF选择性能 - Task.FromResult vs ToListAsync

4
我正在尝试找出使用异步等待方式通过Entity Framework选择数据的最佳方法。在下面的代码中,我有两个选项。
第一个选项使用Task.FromResult。
第二个选项尝试使用异步等待关键字来优化代码。
1.
public Task<IEnumerable<DesignExample>> ExecuteAsync(GetAllExamplesQuery query)
{
    var designExamples = _copyDataDb.DesignExamples.OrderBy(dE => dE.Order).Select(DesignExample.MapFromEntity);

    return Task.FromResult(designExamples);
}

2.

public async Task<IEnumerable<DesignExample>> ExecuteAsync(GetAllExamplesQuery query)
{
    var designExamples = await _copyDataDb.DesignExamples.OrderBy(dE => dE.Order).ToListAsync();

    return designExamples.Select(DesignExample.MapFromEntity);
}
  • 第二个选项在总体性能方面是否比第一个选项更加优秀?
  • 在这种情况下,第二个选项将等待对数据库的调用,但是真的会给我带来任何好处吗?

同一上下文实例上的多个活动操作不受支持。请使用“await”确保在调用此上下文上的另一个方法之前完成任何异步操作。 - Paul Zahra
@PaulZahra 我不确定那个引用如何适用于我的情况? - andreas
基本上,异步执行数据库操作是非常危险的。 - Paul Zahra
@PaulZahra 我不太明白为什么会有危险,也不知道在什么情况下会有危险。你能详细解释一下吗? - andreas
@PaulZahra 我明白了。例如,如果我在未等待第一个调用的情况下对上下文进行另一个异步调用,我可能会遇到麻烦。 - andreas
1个回答

14

这两种方法有着不同的功能。

第一种方法是同步地执行DbContext调用并将结果封装在Task中。这意味着当调用数据库时,调用线程将不会将控制权返回给调用者。该方法的消费者可能不了解为什么ExecuteAsync会阻塞他们的线程。

后者则使用ToListAsync进行异步调用,从而释放调用线程。这意味着调用者可以在此期间使用该线程进行更多的工作,并且当查询完成执行时,程序会恢复执行。

相对于第一个方法,第二个方法是否会增加整体性能?

为了知道这一点,您需要测量您的代码,这主要取决于执行查询所需的时间。请注意,async-await的使用会带来一些开销(虽然对于代码可读性的提升来说,这种开销是微不足道的),它会在幕后生成一个状态机。请注意,您无法对同一个DbContext执行多个查询。

第二个方法将等待对数据库的调用,但在这种情况下,它真的会给我带来什么好处吗?

这样做的主要好处是,在查询运行时,您的线程将自由地进行更多的工作。在ASP.NET等环境中,这意味着ASP.NET线程池可以在此期间处理更多的传入请求,这真的取决于您想实现什么。

Why does the EF 6 tutorial use asychronous calls?中有关于使用异步DB调用的有趣讨论,我认为你会发现它很有趣。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接