C# 使用Dapper并行执行多个查询

C# 使用Dapper并行执行多个查询,c#,task-parallel-library,dapper,C#,Task Parallel Library,Dapper,我尝试使用Dapper和存储过程并行执行三个类似的SQL查询,以在所有查询完成后获得三个类似的结果 这是我的密码: public class SomeReport { private static readonly string ConnectionString = ConfigurationManager.ConnectionStrings["SomeContext"].ToString(); public ReportStatus ReportStatus { get; se

我尝试使用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;
        }
    }
}
公共类报告
{
私有静态只读字符串ConnectionString=ConfigurationManager.ConnectionString[“SomeContext”].ToString();
public ReportStatus ReportStatus{get;set;}
公共长网络服务器时间{get;set;}
公共字符串ReportLastErrorMessage{get;set;}
公共行集[]第一行集{get;set;}
公共行集[]第二行集{get;set;}
公共行集[]第三行集{get;set;}
公开报告(
{
NetworkServerTime=0;
ReportStatus=ReportStatus.NotCreated;
}
公共异步任务GetReportDataAsync(ReportParameters)
{
DynamicParameters requestParameters=新的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=新秒表();
尝试
{
var firstTask=GetRows(“[dbo].[GET\u Report\u FirstRowSet]”,requestParameters);
第二任务=
GetRows(“[dbo].[GET_Report_SecondRowSet]”,requestParameters);
第三任务变量=
GetRows(“[dbo].[GET_Report_ThirdRowSet]”,requestParameters);
allTasks=Task.WhenAll(第一个任务、第二个任务、第三个任务);
FirstRowSet=等待第一个任务;
SecondRowSet=等待第二个任务;
第三个任务=等待第三个任务;
}
捕获(例外情况除外)
{
ReportStatus=ReportStatus.Error;
ReportLastErrorMessage=allTasks?.Exception?.InnerExceptions.Last().Message;
}
最后
{
if(ReportStatus!=ReportStatus.Error)
{
ReportStatus=ReportStatus.Success;
NetworkServerTime=stopWatch.ElapsedMilliseconds;
}
}
秒表复位();
}
专用异步任务GetRows(字符串procName、DynamicParameters参数)
{
使用(var conn=newsqlconnection(ConnectionString))
{
行集[]行集;
尝试
{
var sqlString=string.Concat(procName,“@sinceDateFilter,@untilDateFilter,@countryId”);
var query=await conn.querysync(sqlString,参数,commandTimeout:500);
rowsSet=query.ToArray();
}
捕获(SqlException sqlEx)
{
rowsSet=新的行集[0];
投掷;
}
返回rowsSet;
}
}
}
但是,当我启动调试器和SQLServer探查器时,我看到在创建与它们对应的任务时,查询是按顺序执行的

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

如果我使用调试器和sql探查器,我看到探查器中的第一个查询是在我位于代码
var firstTask=GetRows(“[dbo].[GET_Report_FirstRowSet]”,requestParameters)行时执行的但不是当我在代码行
allTasks=Task.WhenAll(第一个任务、第二个任务、第三个任务)时

这是正确和正常的。
async
/
await
的工作方式是,当第一个不完整的
await
发生时,控制就会返回调用堆栈,在您的情况下,这就是
await conn.QueryAsync
。然而,您仍然只是通过调用异步方法开始了工作。操作未处于等待您调用任务的挂起状态。当所有任务都执行时,因此我们希望操作已经开始<代码>任务。当所有
除了聚合等待步骤之外,什么都不做-它在使事情实际发生方面没有任何作用


因此:我怀疑一切都已按预期进行,但很简单:任务正在按照您要求的顺序开始报告。这是。。。这正是我们所期望的。

您需要先等待所有任务,否则您实际上没有使用
任务。在我看来,所有的
任务应该已经在做您想要的事情了(上面的注释中有一些小错误)-是什么让您认为它们实际上是顺序的,而不是仅仅因为它们是如何开始的而按顺序报告?另外:SqlClient可能对什么是/不是有效的有意见here@Marc如果我使用调试器和sql探查器,我看到探查器中的第一个查询是在我位于代码
var firstTask=GetRows(“[dbo].[GET_Report_FirstRowSet]”,requestParameters)行时执行的但不是当我在代码行
allTasks=Task.WhenAll(第一个任务、第二个任务、第三个任务)时嗨,为什么不使用?