带有异步Dapper方法的CancellationToken

本文关键字:CancellationToken 方法 Dapper 异步 | 更新日期: 2023-09-27 18:19:37

我正在使用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

谢谢!

带有异步Dapper方法的CancellationToken

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

dapper中的第一个异步方法没有公开取消令牌;当我试图将它们作为一个可选参数(作为一个单独的重载,以避免破坏现有的程序集)添加时,事情与"模糊方法"编译问题非常混淆。因此,我不得不通过一个单独的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命令在这里有些有用,也是我在集成测试中使用的命令。

您可以通过添加以下行来修复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库并享受:)

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

var sqlConn = db.Database.Connection as SqlConnection;
sqlConn.Open();
_cmd = new SqlCommand(textCommand, sqlConn);
_cmd.ExecuteNonQuery();

并取消CCD_ 11

_cmd.Cancel();

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

相关文章:
  • 没有找到相关文章