優れたパフォーマンスを実現するために、Web ガーデン (複数の ASP.NET ワーカー プロセス) で実行される次のコードがあります。このコード フラグメント以外はすべて問題ありません。
UserTaskRelation には一意のインデックスがあり、ここに私のコードがあります...
// There is Unique Index for TaskID and UserID
var t = db.UserTaskRelations.FirstOrDefault(
x=> x.TaskID == taskID
&& x.UserID == userID);
if(t==null){
t = new UserTaskRelation { TaskID=taskID, UserID = userID };
db.UserTaskRelations.AddObject(t);
}
t.LastUpdated = DateTime.UtcNow;
db.SaveChanges();
このコードは、前の要求がまだキューにあり、要求の 1 つが失敗しているときに、同じユーザーが同じタスクの更新ページにアクセスすると、最後の行で失敗します。
これはマルチプロセス環境で実行されるため、ロックは役に立ちません。また、同じことを実行する複数の Web サーバーがあるため、mutex によるロックも役に立ちません。
このようにすべてを Transaction にまとめました...
using(TransactionScope scope = new TransactionScope(
TransactionScopeOption.Required))
{
// all of above code here...
scope.Complete();
}
これはまだ役に立ちません... 100回の操作のうち、1〜5%が失敗することがわかります。ストアドプロシージャなどのように、これを安全に挿入する方法はありますか?
私は現在、汚い回避策を行っています...
1. Try Logic
2. Catch Exception
3. Try Get Logic (assuming it exists)
しかし、ロジックの一部として Catching Exception を記述するのは好きではありません。