我正在使用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
?谢谢!
答案 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
时,错误就消失了。