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

Ped*_*ree 24 .net c# 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();
}
Run Code Online (Sandbox Code Playgroud)

当我按下F12QueryAsync,它指向我

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

CancellationToken它的签名没有.

问题:

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

谢谢!

Mar*_*ell 38

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

dapper中的第一个异步方法没有公开取消令牌; 当我尝试将它们添加为可选参数(作为单独的重载,以避免破坏现有的程序集)时,事情与"模糊方法"编译问题非常混淆.因此,我不得不通过单独的API公开它; 输入CommandDefinition:

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

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

至于问题:

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

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

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

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

  • 这是作者自己的一个很好的答案。感谢 Marc 提供替代 API!好吧,我可以捕获“SqlException”而不是“OperationCancelledException”,我将在这里处理逻辑。再次感谢! (3认同)