使用 Dapper 并行执行多个查询

我尝试使用 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 时,我发现在创建与其对应的任务时,查询是按顺序执行的。


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


HUX布斯
浏览 191回答 2
2回答

慕码人8056858

如果我使用调试器和 sql-profiler,我会看到探查器中的第一个查询是在我位于代码行时执行的,var firstTask = GetRows("[dbo].[GET_Report_FirstRowSet]", requestParameters);但不是在我位于代码行时执行的allTasks = Task.WhenAll (firstTask, secondTask, thirdTask);这是正确且正常的。async/ 的工作方式await是,一旦发生第一个不完整的await情况,控制权就会返回调用堆栈,在您的情况下是await conn.QueryAsync<RowSet>.&nbsp;但是,您仍然只需通过调用 async 方法即可开始工作。该操作不会处于某种挂起状态等待您调用Task.WhenAll,因此我们预计它已经开始。除了聚合等待Task.WhenAll步骤之外,不执行任何操作- 它在使事情实际发生方面没有任何作用。所以:我怀疑一切都已经按预期工作,但简单地说:任务报告为按照您请求的顺序开始。这正是我们所期望的。

胡说叔叔

因为所有任务都已在减速时间运行。当您从返回的 GetRow 方法分配任务时,您已经让它开始了。然后使用 Task.WhenAll 创建一个新任务,当所有子任务完成时,该任务将返回已完成。但你也没有等到这个任务。这样就保证了当三个任务完成时用await关键字执行完成。如果您可以用一个单独的任务包装所有执行,您可以像这样并行调用所有执行var queries = new[] {&nbsp;&nbsp; &nbsp; "[dbo].[GET_Report_FirstRowSet]",&nbsp;&nbsp; &nbsp; "[dbo].[GET_Report_SecondRowSet]",&nbsp;&nbsp; &nbsp; "[dbo].[GET_Report_ThirdRowSet]"&nbsp;};var tasks = queries.Select(query => new Task(()=>{&nbsp; &nbsp; return GetRows(query, requestParameters);})).ToArray();Task.WaitAll(tasks);
打开App,查看更多内容
随时随地看视频慕课网APP