43

我正在使用 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();
}

当我按下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
     );

它的签名上没有CancellationToken

问题:

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

谢谢!

4

4 回答 4

76

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

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

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

然后将取消令牌沿着链传递到所有预期的地方;实际使用它是 ADO.NET 提供者的工作,但是;它似乎在大多数情况下都有效。请注意,如果操作正在进行,它可能会导致 aSqlException而不是a;OperationCancelledException这再次取决于 ADO.NET 提供程序,但很有意义:您可能中断了一些重要的事情;它表现为一个关键的连接问题。

至于问题:

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

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

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

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

于 2014-08-28T09:26:25.730 回答
0

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

    internal IDbCommand SetupCommand(IDbConnection cnn, Action<IDbCommand, object> paramReader)
    {
        var cmd = cnn.CreateCommand();

#if ASYNC
        // We will cancel our IDbCommand
        CancellationToken.Register(() => cmd.Cancel());
#endif

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

于 2016-01-24T21:22:16.373 回答
0

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

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

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

并取消SqlCommand

_cmd.Cancel();
于 2019-10-16T19:00:30.103 回答
-3

我将一个SqlConnection用于多个线程。然后当我改变它以便每个人都Thread创建它自己SqlConnection时,错误消失了。

于 2018-04-06T16:38:04.627 回答