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 プロバイダーの仕事ですが、ほとんどの場合に機能するようです。操作が進行中SqlExceptionの場合は、 ではなくになる可能性があることに注意してください。OperationCancelledExceptionこれもまた ADO.NET プロバイダーによるものですが、非常に理にかなっています。何か重要なことを中断する可能性があります。重大な接続の問題として表面化します。

質問について:

ソリューション全体にコンパイラ エラーがないと仮定して、スニペットが完全にビルド可能なのはなぜですか?

なぜなら...期待どおりに動作しない場合でも、有効なC#だからです。

tokenSource.Cancel() を呼び出すと本当にメソッドがキャンセルされるかどうかをテストできないので、許してください。長時間実行される SQL クエリを生成する方法がわからないためです。.Cancel() は本当にメソッドをキャンセルし、OperationCancelledException をスローしますか?

ADO.NET プロバイダー固有ですが、通常は動作します。「長時間実行されるSQLクエリを生成する方法」の例として; ここでは、SQL サーバーの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 ライブラリを再構築してお楽しみください :)

于 2016-01-24T21:22:16.373 に答える