NugetのDapper1.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()
を呼び出すとメソッドが本当にキャンセルされるかどうかをテストできないことをお許しください。 .Cancel()
は本当にメソッドをキャンセルしてOperationCancelledException
をスローしますか?ありがとうございました!
キャンセルトークンをパラメータオブジェクトとして渡します。それはうまくいきません。
Dapperの最初の非同期メソッドはキャンセルトークンを公開しませんでした。それらをオプションのパラメーターとして(既存のアセンブリを壊さないように、別個のオーバーロードとして)追加しようとすると、 「あいまいなメソッド」のコンパイルの問題と非常に混同されました 。その結果、別のAPIを介してこれを公開する必要がありました。 CommandDefinition
と入力します。
val = (await conn.QueryAsync<int>(
new CommandDefinition(query, cancellationToken: tokenSource.Token)
).FirstOrDefault();
次に、キャンセルトークンをチェーンのすべての予想される場所に渡します。実際に使用するのはADO.NETプロバイダーの仕事ですが、;ほとんどの場合は機能するようです。操作が進行中の場合は、SqlException
ではなくOperationCancelledException
になる可能性があることに注意してください。これもADO.NETプロバイダーに依存しますが、非常に理にかなっています。重要な何かを中断した可能性があります。それは重大な接続の問題として表面化します。
質問について:
ソリューション全体にコンパイラエラーがないと仮定して、スニペットを完全にビルドできるのはなぜですか?
なぜなら...期待どおりに機能しない場合でも、有効なC#です。
長時間実行されるSQLクエリを生成する方法がわからないため、tokenSource.Cancel()を呼び出すと実際にメソッドがキャンセルされるかどうかをテストできないため、ご容赦ください。 .Cancel()は実際にメソッドをキャンセルし、OperationCancelledExceptionをスローしますか?
ADO.NETプロバイダー固有ですが、通常は機能します。 「長時間実行されるSQLクエリを生成する方法」の例として;ここでは、SQLサーバーのwaitfor delay
コマンドがいくらか便利であり、統合テストで使用しています。
次の行を追加することで、 SqlMapper.cs in Dapper lib を修正できます。
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
独自のDapperlibを再構築してお楽しみください:)
SqlConnection
を使用してみて、キャンセル時に例外をキャッチしてください
var sqlConn = db.Database.Connection as SqlConnection;
sqlConn.Open();
_cmd = new SqlCommand(textCommand, sqlConn);
_cmd.ExecuteNonQuery();
SqlCommand
をキャンセルします
_cmd.Cancel();
複数のスレッドに1つのSqlConnection
を使用していました。そして、各Thread
が独自のSqlConnection
を作成するように変更すると、エラーは消えました。