【问题标题】:Execute multiple queries in parallel with Dapper使用 Dapper 并行执行多个查询
【发布时间】:2019-08-11 08:25:58
【问题描述】:

我尝试使用 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;
        }
        finally
        {
            if (ReportStatus != ReportStatus.Error)
            {
                ReportStatus = ReportStatus.Success;
                NetworkServerTime = stopWatch.ElapsedMilliseconds;
            }

        }
        stopWatch.Reset();
    }

    private async Task<RowSet[]> GetRows(string procName, DynamicParameters parameters)
    {
        using (var conn = new SqlConnection(ConnectionString))
        {
            RowSet[] rowsSet;

            try
            {
                var sqlString = string.Concat(procName, " @sinceDateFilter, @untilDateFilter, @countryId");
                var query = await conn.QueryAsync<RowSet>(sqlString, parameters, commandTimeout: 500);
                rowsSet = query.ToArray();
            }
            catch (SqlException sqlEx)
            {
                rowsSet = new RowSet[0];
                throw;
            }

            return rowsSet;
        }
    }
}

但是当我启动调试器和 SQL Server Profiler 时,我看到查询是在创建对应的任务时按顺序执行的。

如何让查询同时开始运行并并行运行?

【问题讨论】:

  • 你需要先await allTasks,否则你实际上并没有使用Task.WhenAll
  • 对我来说,它看起来应该已经在做你想做的事了(除了上面的评论之外的小细节) - 是什么让你认为它们在这里实际上是连续的,而不是仅仅因为顺序被报告他们是如何开始的?另外:SqlClient 可能对这里的有效/无效有意见
  • @Marc 如果我使用调试器和 sql-profiler,我看到分析器中的第一个查询是在我在代码行 var firstTask = GetRows("[dbo].[GET_Report_FirstRowSet]", requestParameters); 时执行的,但不是在我在代码行时代码allTasks = Task.WhenAll (firstTask, secondTask, thirdTask);
  • 嗨,为什么不用multiple query

标签: c# task-parallel-library dapper


【解决方案1】:

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

这是正确和正常的。 async/await 的工作方式是,一旦第一个不完整的await 发生,控制权就会返回调用堆栈,在你的情况下是await conn.QueryAsync&lt;RowSet&gt;。但是,您仍然只需调用异步方法就可以开始了。该操作并未处于等待您致电Task.WhenAll 的待处理状态,因此我们预计它已经开始。 Task.WhenAll 除了聚合 await 步骤之外,什么都不做任何事情 - 它对使事情真正发生没有任何作用。

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

【讨论】:

    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多