1

UnityをIoCとして使用しているasp.netMVC4アプリケーションがあります。私のコントローラーのコンストラクターはリポジトリーを取り、そのリポジトリーはUnitOfWork(DBContext)を取ります。同じセッションからの複数のajaxリクエストが速すぎるまで、すべてが正常に機能しているようです。Store update, insert, or delete statement affected an unexpected number of rows (0)同時実行の問題が原因でエラーが発生します。これは、メソッドがajaxリクエストから呼び出されたように見えるものです。

public void CaptureData(string apiKey, Guid sessionKey, FormElement formElement)
{
        var trackingData = _trackingService.FindById(sessionKey);
        if(trackingData != null)
        {
             formItem = trackingData.FormElements
                          .Where(f => f.Name == formElement.Name)
                          .FirstOrDefault();

             if(formItem != null)
             {
                formItem.Value = formElement.Value;
                _formElementRepository.Update(formItem);
             }
        }
}

これは、ajaxリクエストが迅速に、つまり高速に発生した場合にのみ発生します。リクエストが通常の速度で発生する場合、すべてが正常に見えます。アプリが追いつくのに時間がかかるようなものです。リポジトリで同時実行チェックをどのように処理する必要があるのか​​わからないので、更新を見逃すことはありません。また、「MultipleActiveResultSets」をtrueに設定しようとしましたが、役に立ちませんでした。

4

1 に答える 1

1

コメントで述べたように、行バージョンの列を使用しています。この列のポイントは、同じ行が同時に上書きされないようにすることです。2つの操作があります。

  • レコードの読み取り-レコードと現在の行のバージョンを読み取ります
  • レコードの更新-指定されたキーと行のバージョンでレコードを更新します。行バージョンは自動的に更新されます

これらの操作が同時リクエストによって実行される場合、次のメッセージを受け取る可能性があります。

  • リクエストA:レコードの読み取り
  • リクエストB:レコードの読み取り
  • リクエストA:レコードの書き込み-行バージョンを変更します!
  • リクエストB:レコードの書き込み-レコードの読み取り中に取得された行バージョンのレコードが存在しないため、例外が発生します

例外は、更新されたレコードの新しいバージョンがすでに存在するため、廃止されたデータを更新しようとしていることを通知するために発生します。通常、データを更新し(データベースから現在のレコードを再ロードすることにより)、それらを再保存する必要があります。並行性の高いシナリオでは、データベースがこれを防ぐように設計されているため、この処理が何度も繰り返される可能性があります。オプションは次のとおりです。

  • 行バージョンを削除し、リクエストが必要に応じて値を上書きできるようにします。本当に同時リクエスト処理が必要で、「ある程度の」価値があることに満足している場合は、これが最適な方法かもしれません。
  • 同時リクエストを許可しません。すべての更新を処理する必要がある場合は、おそらく実際の順序も必要です。このような場合、アプリケーションは同時リクエストを許可しないでください。
  • 代わりにSQL/ストアドプロシージャを使用してください。テーブルヒントを使用すると、読み取り操作中にレコードをロックでき、最初の要求が変更を保存してトランザクションをコミットまたはロールバックする前に、他の要求がそのレコードを読み取ることができなくなります。
于 2012-08-14T11:57:33.150 に答える