为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Dapper 并行执行多个查询

使用 Dapper 并行执行多个查询

C#
HUX布斯 2023-08-20 15:28:59
我尝试使用 Dapper 和存储过程并行执行三个相似的 SQL 查询,以在所有查询完成后获得三个相似的结果。这是我的代码:public class SomeReport{    private static readonly string ConnectionString = ConfigurationManager.ConnectionStrings["SomeContext"].ToString();    public ReportStatus ReportStatus { get; set; }    public long NetworkServerTime { get; set; }    public string ReportLastErrorMessage { get; set; }    public RowSet[] FirstRowSet { get; set; }    public RowSet[] SecondRowSet { get; set; }    public RowSet[] ThirdRowSet { get; set; }    public Report()    {        NetworkServerTime = 0;        ReportStatus = ReportStatus.NotCreated;    }    public async Task GetReportDataAsync(ReportParameters parameters)    {        DynamicParameters requestParameters = new DynamicParameters();        requestParameters.Add("@sinceDateFilter", parameters.SinceDate?.Date, DbType.DateTime);        requestParameters.Add("@untilDateFilter", parameters.UntilDate?.Date, DbType.DateTime);        requestParameters.Add("@countryId", parameters.CountryId, DbType.Int32);        ReportLastErrorMessage = null;        Task allTasks = null;        var stopWatch = new Stopwatch();        try        {            var firstTask = GetRows("[dbo].[GET_Report_FirstRowSet]", requestParameters);            var secondTask =                GetRows("[dbo].[GET_Report_SecondRowSet]", requestParameters);            var thirdTask =                GetRows("[dbo].[GET_Report_ThirdRowSet]", requestParameters);            allTasks = Task.WhenAll(firstTask, secondTask, thirdTask);            FirstRowSet = await firstTask;            SecondRowSet = await secondTask;            ThirdRowSet = await thirdTask;        }        catch (Exception ex)        {            ReportStatus = ReportStatus.Error;            ReportLastErrorMessage = allTasks?.Exception?.InnerExceptions.Last().Message;        }但是,当我启动调试器和 SQL Server Profiler 时,我发现在创建与其对应的任务时,查询是按顺序执行的。如何使查询同时开始运行并并行运行?
查看完整描述

2 回答

?
慕码人8056858

TA贡献1803条经验 获得超6个赞

如果我使用调试器和 sql-profiler,我会看到探查器中的第一个查询是在我位于代码行时执行的,var firstTask = GetRows("[dbo].[GET_Report_FirstRowSet]", requestParameters);但不是在我位于代码行时执行的allTasks = Task.WhenAll (firstTask, secondTask, thirdTask);

这是正确且正常的。async/ 的工作方式await是,一旦发生第一个不完整的await情况,控制权就会返回调用堆栈,在您的情况下是await conn.QueryAsync<RowSet>但是,您仍然只需通过调用 async 方法即可开始工作。该操作不会处于某种挂起状态等待您调用Task.WhenAll,因此我们预计它已经开始。除了聚合等待Task.WhenAll步骤之外,不执行任何操作- 它在使事情实际发生方面没有任何作用。

所以:我怀疑一切都已经按预期工作,但简单地说:任务报告为按照您请求的顺序开始。这正是我们所期望的。


查看完整回答
反对 回复 2023-08-20
?
胡说叔叔

TA贡献1804条经验 获得超8个赞

因为所有任务都已在减速时间运行。当您从返回的 GetRow 方法分配任务时,您已经让它开始了。然后使用 Task.WhenAll 创建一个新任务,当所有子任务完成时,该任务将返回已完成。但你也没有等到这个任务。


这样就保证了当三个任务完成时用await关键字执行完成。


如果您可以用一个单独的任务包装所有执行,您可以像这样并行调用所有执行



var queries = new[] { 

    "[dbo].[GET_Report_FirstRowSet]", 

    "[dbo].[GET_Report_SecondRowSet]", 

    "[dbo].[GET_Report_ThirdRowSet]" 

};


var tasks = queries.Select(query => new Task(()=>{

    return GetRows(query, requestParameters);

})).ToArray();


Task.WaitAll(tasks);


查看完整回答
反对 回复 2023-08-20
  • 2 回答
  • 0 关注
  • 190 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信