C# 使用Dapper并行执行多个查询
我尝试使用Dapper和存储过程并行执行三个类似的SQL查询,以在所有查询完成后获得三个类似的结果 这是我的密码: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
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(第一个任务、第二个任务、第三个任务)时代码>嗨,为什么不使用?