我们遇到问题是我们使用Dapper异步同时执行大量查询(大到100-200)并最终获得超时异常。我认为正在发生的事情是Dapper正在做await ... [connection].OpenAsync(...)
(seen here),它允许其他异步代码也打开连接,然后当代码返回到原始打开的连接时开始查询sql超时已经过去了。我的问题有一种方法或做法来防止这种情况。我们考虑过的一个解决方案就是增加sql超时。另一个是减少我们一次从DB查询的对象的数量。然而,感觉就像我们做得不对,想要伸出手来看看是否有更好的方法。在此先感谢,如果这是重复的,我很抱歉,我找不到任何其他描述此问题的解决方案。
以下是执行查询的代码:
public async Task<bool> ThingExistsAsync(int? somethingId, int somethingTypeId)
{
using (var conn = connectionFactory.GetEddsPerformanceConnection())
{
return await conn.QueryFirstOrDefaultAsync<int>(Resources.Event_ReadCountBySomethingTypeAndId,
new { somethingId, somethingTypeId }) > 0;
}
}
致电代码:
Task.WhenAll(listOfThings.Select(t => ThingExistsAsync(t.Id, t.Type)));
以下是例外:
System.Data.SqlClient.SqlException (0x80131904): Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
at System.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__174_0(Task`1 result)
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Dapper.SqlMapper.<QueryRowAsync>d__24`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Company.Product.Data.Repositories.ThingRepository.<ThingExistsAsync>d__17.MoveNext()
...
ClientConnectionId:059604ea-1123-4d8d-ba00-071ed3a0b962
Error Number:-2,State:0,Class:11
答案 0 :(得分:1)
我遇到了同样的问题。我的SqlConnection对象指定了连接超时,但是dapper查询没有尊重它,所以我传递了我的连接超时值,但当然你可以传递任何你喜欢的内容。
这是我为解决问题所做的工作:
var result = await conn.QueryAsync(sqlQueryText, new { param = "paramValue" }, commandTimeout: conn.ConnectionTimeout);
答案 1 :(得分:-1)
您可以考虑切换到Parallel.ForEach并设置Max degree of Parallelism以限制同时访问数据库但仍保持多线程方法的线程数。