Dapper async / await connection timeout

时间:2018-03-04 01:24:47

标签: c# sql dapper connection-timeout

我们遇到问题是我们使用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

2 个答案:

答案 0 :(得分:1)

我遇到了同样的问题。我的SqlConnection对象指定了连接超时,但是dapper查询没有尊重它,所以我传递了我的连接超时值,但当然你可以传递任何你喜欢的内容。

这是我为解决问题所做的工作:

var result = await conn.QueryAsync(sqlQueryText, new { param = "paramValue" }, commandTimeout: conn.ConnectionTimeout);

答案 1 :(得分:-1)

您可以考虑切换到Parallel.ForEach并设置Max degree of Parallelism以限制同时访问数据库但仍保持多线程方法的线程数。

https://msdn.microsoft.com/en-us/library/system.threading.tasks.paralleloptions.maxdegreeofparallelism(v=vs.110).aspx