私は金銭取引を扱っている状況で働いています。
たとえば、ユーザーウォレットのテーブルがあり、その行に残高があります。
UserId; Wallet Id; Balance
現在、当社のWebサイトおよびWebサービスでは、特定のトランザクションが発生するたびに、次のことを行う必要があります。
トランザクションの全期間にわたってその行/エンティティをロックするための正しい方法は何ですか?
私が読んだことから、EFがエンティティにマークを付け、それをDBに保存するときにそのマークを比較するいくつかの解決策がありますが、別のユーザー/プログラムがすでに金額を編集している場合はどうなりますか?
EFでこれを達成できますか?そうでない場合、他にどのようなオプションがありますか?
ストアドプロシージャを呼び出すと、行を適切にロックできる可能性があります。これにより、プログラムAがロックされている間、SQL Serverのその行に他のユーザーがアクセスできなくなりますか?
EFには組み込みのロックメカニズムがないため、おそらく次のような生のクエリを使用する必要があります。
using (var scope = new TransactionScope(...))
{
using (var context = new YourContext(...))
{
var wallet =
context.ExecuteStoreQuery<UserWallet>("SELECT UserId, WalletId, Balance FROM UserWallets WITH (UPDLOCK) WHERE ...");
// your logic
scope.Complete();
}
}
entity Frameworkのトランザクションに分離レベルを設定して、他の誰もそれを変更できないようにすることができます。
YourDataContext.Database.BeginTransaction(IsolationLevel.RepeatableRead)
RepeatableReadの概要:クエリで使用されるすべてのデータにロックが設定され、他のユーザーがデータを更新できないようにします。繰り返し不可能な読み取りを防ぎますが、ファントム行は引き続き可能です。
トランザクションデータベースの要点は、データの利用者がデータのビューをどの程度分離するかを決定することです。
トランザクションが serialized であるかどうかに関係なく、他の誰かが、変更したがコミットしなかったのと同じデータに対してダーティ読み取りを実行できます。
最初にビューの整合性に関心を持ち、次にそのビューの品質の低下のみを受け入れて、必要であると確信できるシステムパフォーマンスを向上させる必要があります。
すべてをTransactionScope
でSerialized
分離レベルでラップすれば、個人的には間違いはありません。分離レベルを下げるのは、それが本当に必要であることがわかった場合のみです(つまり、問題が発生した場合は問題ない場合があります)。
誰かがここでこれについて尋ねます: SQL Server:ストアドプロシージャでのダーティリードの防止