0

ある種の金融システムを作成しようとしており、高同時実行モードで口座残高を更新したいと考えています。もちろん、実際の値を読み取って更新するには、特定のアカウント レコードへの排他的アクセスが必要です。残念ながら、EF を使用して既存のレコードの読み取りをシリアル化することはできません。質問: EF に次のような更新を強制的に生成させることは可能ですか?

update MyTable
set Balance=Balance+xxx  //where xxx my balance increment
where ID=yyy

それ以外の

update MyTable
set Balance=NewValue
where ID=...

または、他の正しいアプローチを逃しましたか?現在、考えられる解決策は 1 つしかありません。Entity Framework と対話せずに、直接 SQL コマンドを使用して別の接続を介して残高を更新することです。

再現方法: ASP.NET アプリケーションを作成しています。各スレッドには、データベースに接続するための独自の DbContext があります。私のモデルの非常に単純化された形式は次のとおりです。

public class Account{
    public int Id {get; set;}
    public decimal Balance {get; set;}
}
public class Entry {
    public int Id {get; set;}
    public int AccountId {get; set;}
    public decimal Amount {get; set;}
}

エントリを投稿した直後に、アカウントの残高を更新する必要があります。マルチユーザー サイト アクセスをエミュレートするために JMeter を使用しています。最も簡単なテストは、数十のスレッドに同じ金額を投稿し、その後のすべてのアカウントの合計残高を計算することです。たとえば、20 個のスレッドがあり、各スレッドに 10 件のリクエストがあり、それぞれの投稿金額が 50 である場合、合計残高として 10000 を取得する必要があります。ここでデータベース ロックを慎重に処理する必要があることはわかっており、低レベルの DB アクセスでこれを行う方法もわかっています。外部のものなしで Entity Framework を使用する方法を見つけたかっただけです。私はすでにTransactionScopeたくさん遊んでいますが、現在の残高値の読み取りアクセスをシリアル化できないようです。

4

1 に答える 1

0

これは、Entity Framework がこの仕事には不適切なツールであるように思えます。データベースとのすべてのやり取りを完全に置き換えることを意図したものではありません。あなたが言っていることを行うには、SQLを直接実行するのが最善の策です。

ただし、データベース構造を変更することをお勧めします。200 (20 スレッド * 10 リクエスト) の更新があると述べました。活動表を作ってみませんか。これらの 200 回の更新は、アクティビティ テーブルへの 200 回の挿入に変換されます。を設定する代わりに、アクティビティ テーブルAmount = Amount + 50に挿入するだけです。50このようにして、スレッドが他のスレッドを踏む可能性はありません。さらに、トランザクションの履歴を取得し、取り消す必要がある場合は、簡単に行うことができます。

編集

質問を読み直したところです。あなたのEntryテーブルは私が提案しているもののようです。その場合、データベースの正規化によりBalance、アカウントから削除する必要があると言われます。表示する必要があるときにその場で計算します。

于 2013-08-08T17:52:53.497 に答える