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