使用异步Dapper方法取消语句?

时间:2014-08-28 04:35:55

标签: c# .net async-await dapper cancellation-token

我正在使用Nuget的Dapper 1.31。我有这个非常简单的代码片段,

string connString = "";
string query = "";
int val = 0;
CancellationTokenSource tokenSource = new CancellationTokenSource();
using (IDbConnection conn = new SqlConnection(connString))
{
    conn.Open();
    val = (await conn.QueryAsync<int>(query, tokenSource.Token)).FirstOrDefault();
}

当我在QueryAsync上按 F12 时,它指向我

public static Task<IEnumerable<T>> QueryAsync<T>
     (
        this IDbConnection cnn, 
        string sql, 
        dynamic param = null, 
        IDbTransaction transaction = null, 
        int? commandTimeout = null, 
        CommandType? commandType = null
     );

签名上没有CancellationToken

问题:

  • 为什么片段完全可构建假设整个解决方案没有编译器错误?
  • 请原谅我,因为我无法测试调用tokenSource.Cancel()是否真的会取消该方法,因为我不知道如何生成长时间运行的SQL查询。 .Cancel()是否真的会取消该方法并抛出OperationCancelledException

谢谢!

4 个答案:

答案 0 :(得分:32)

您正在将取消令牌作为参数对象传递;这是行不通的。

dapper中的第一个异步方法没有公开取消令牌;当我尝试将它们添加为可选参数时(作为单独的重载,以避免破坏现有的程序集),things got very confused with "ambiguous method" compilation problems。因此,我不得不通过单独的API公开它;输入CommandDefinition

val = (await conn.QueryAsync<int>(
    new CommandDefinition(query, cancellationToken: tokenSource.Token)
).FirstOrDefault();

然后将取消令牌传递到链中的所有预期位置;实际上使用它是ADO.NET提供者的职责,但是;它似乎适用于大多数情况。请注意,如果操作正在进行,它可能会导致SqlException而不是OperationCancelledException;这又归结于ADO.NET提供商,但是很有意义:你可能已经打断了一些重要的东西;它表面是一个关键的连接问题。

至于问题:

  

为什么假设整个解决方案没有编译器错误,代码片段是否完全可构建?

因为......它是有效的C#,即使它没有达到预期效果。

  

原谅我,因为我无法测试调用tokenSource.Cancel()是否真的会取消该方法,因为我不知道如何生成长时间运行的sql查询。 .Cancel()是否真的会取消该方法并抛出OperationCancelledException?

特定于ADO.NET提供程序,但是它通常有效。以“如何生成长时间运行的sql查询”为例; SQL Server上的waitfor delay命令在这里有点用处,是我在集成测试中使用的。

答案 1 :(得分:2)

您可以通过添加以下行来修复SqlMapper.cs中的Dapper lib



      array(2) {
      [0]=>
      object(Record)#20 (3) {
        ["name"]=>
        string(32) "Bank 1 - Account"
        ["balance"]=>
        string(7) "2000.00"
      }
      [1]=>
      object(Record)#21 (3) {
        ["name"]=>
        string(32) "Bank 2 - Account"
        ["balance"]=>
        string(8) "1000.00"
      }
    }

重建你自己的Dapper lib并享受:)

答案 2 :(得分:0)

尝试使用SqlConnection并在取消时捕获异常

var sqlConn = db.Database.Connection as SqlConnection;
sqlConn.Open();

_cmd = new SqlCommand(textCommand, sqlConn);
_cmd.ExecuteNonQuery();

并取消SqlCommand

_cmd.Cancel();

答案 3 :(得分:-1)

我使用一个SqlConnection用于多个线程。然后当我更改它以便每个Thread创建它自己的SqlConnection时,错误就消失了。