在 Tasks 中包装 Entity Framework Stored Proc 执行代码

Wrapping Entity Framework Stored Proc execution code in Tasks

我对 C# 中异步行为的了解有点生疏,我想知道将某些代码更改为异步是否会对我们有益,或者它是否实际上会降低代码的效率。

我有一组方法,每个方法都通过 entity framework 执行一个存储过程。我们 return 一个 IEnumerable<SomeDataType>.

此集合中的每个方法都可以 运行 独立于其他方法,因此我开始考虑 运行 并行处理它们。

一位前同事告诉我的关于数据库查询所有 运行ning 同步,以及将数据库调用代码包装在任务中会减慢系统速度的事情突然出现在我的脑海中。

我们的方法是这样的:

private IEnumerable<Models.Permission> PermissionsForUser(Context entities,int userId)
{
    var userperms = entities.sssp_GetUserPermissions(userId);
    return ...
}

任务并行库不会减慢代码速度,.net 中引入的库是为了利用当今存在的多核处理器。

因此,如果您向数据库发出两个查询,两者并不相互依赖,那么您可以创建两个任务并调用将并行执行您的代码的数据库。

默认 运行 任务使用线程池,如果你创建长 运行 任务会减慢速度,因为调用数据库可能很长 运行 我建议你创建长任务运行 任务使用 TaskCreationOptions.LongRunning

示例代码如:

 Task[] tasks = new Task[2];

task[0] = Task.Factory.StartNew(calltodatabase1
                      , TaskCreationOptions.LongRunning
                      , cancellationTokenSource.Token); 
task[1] = Task.Factory.StartNew(calltodatabase2
                      , TaskCreationOptions.LongRunning
                      , cancellationTokenSource.Token); 

Task.WaitAll(tasks);

Can there be benefits to wrapping DB calling code in Tasks?

这取决于。如果 Task 你的意思是 "using a naturally asynchronous API exposed by the data provider",例如 ADO.NET 或 Entity Framework 暴露的 XXXAsync,那么它 可能 如果你有并发的好处请求命中您的数据库,并且您希望释放线程以同时处理其他请求。它肯定不会加速您的查询。

Will I end up slowing our system down by wrapping DB calls in Tasks?

同样,这取决于。您的第一个问题以及您所说的 "Tasks" 的意思也是如此。你必须记住 Task != Thread。如果你想通过调用 Task.Run 来包装你的数据库查询,你将有效地使用 "async over sync" 反模式。它最终可能也会减慢您的查询速度,您必须进行基准测试才能确定。

Are DB queries all executed in a synchronous fashion?

数据库查询可以同步或异步执行,具体取决于提供程序公开的 API。进行数据库调用自然是异步的,这意味着不需要为这些查询使用任何额外的线程来释放正在使用的线程。如果您有多个可以同时执行的查询,那么您可能会受益于使用那些异步 API 的查询。