2016-09-09 3 views
0

私はこのような機能をコントローラに注入されるシングルトンサービスに持っています。私が心配何非同期関数は、別のインスタンスが実行されているのと同時に実行できますか?

public async Task<ResponseModel> Put(BoardModel request) 
{ 
    var board = await dbService.GetBoardAsync(request.UserId, request.TargetId, request.Ticker); 

    // Update the model 
    // ... 

    var response = await dbService.SetBoardAsync(request.UserId, request.TargetId, request.Ticker, request); 

    return new ResponseModel 
    { 
     ResponseStatus = response.Successful(replacements: 1) ? ResponseStatus.Success : ResponseStatus.Failure 
    }; 
} 

は、競合状態である機能の2つのインスタンスが同時に実行されている、もう1つは、DB内のエントリを上書きする場合は、言います。

これは可能ですか?それが起こる可能性は非常に低いですが、私はまだ少し心配しています。

ありがとうございます!

+0

次に、データベースで適切なロックレベルまたは同時実行性オプションを使用します。このコードでは、非同期または非同期に2回実行することはできません。 –

+0

@DavidLこれはWebアプリケーションです。 *非同期でマークされていない場合でも、複数のHTTP PUTリクエストが複数の呼び出しを引き起こします。あなたが誤解している@PanagiotisKanavosをロックする理由はありません。 –

+0

コードロック、データベースロックではありません。営業担当者がトランザクションデータが上書きされたり期限切れになることを心配している場合は、Webアプリケーションレベルではなく、データベースレベルで処理する必要があります。 –

答えて

1

はい、サーバーに複数のスレッド(実稼働可能なWebサーバー)がある場合、2つ以上のスレッドが同じコードブロックを同時に実行できます。このような状況を処理する典型的な方法は、楽観的な並行処理です。つまり、EFはレコードを保存しようとします(は問題なしとすると、となります)、レコードが変更されてしまうと、例外が返されます(具体的にはOptimisticConcurrencyException) 。設定方法については、this ASP.NET getting started articleをご覧ください。基本的には、rowversionカラムをデータベーステーブルに追加するだけです。行が更新されるたびに、その列の値が変更されます。したがって、EFは更新しようとしているレコードの値を現在テーブルにあるものでチェックできます。それらが同じであれば、更新を続けることができます。そうでなければ、他の何かがレコードを修正し、更新を停止します。返された例外をキャッチすることで、データをリロードして別の更新を試みることで、適切に対応することができます。

並行処理の問題が複数回発生する可能性は非常に低いですが、その場合には、例外を処理するためにPollyNuget)のようなものを使用することをお勧めします。とりわけ、例外が発生しなくなるまで、設定した回数または永遠に再試行することができます。これにより、並行処理の競合が複数あった場合でも、レコードが最終的に更新されることが保証されます。

Policy 
    .Handle<OptimisticConcurrencyException>() 
    .RetryForever((exception, context) => { 
     // resolve concurrency issue 
     // See: https://msdn.microsoft.com/en-us/data/jj592904.aspx 
    }) 
    .Execute(() => { 
     db.SaveChanges(); 
    }); 
関連する問題