Простой и надежный способ сериализации транзакции EF SQL Server заключается в использовании Application Lock .
Добавьте этот метод в свой DbContext:
public void GetAppLock(string lockName)
{
var sql = "exec sp_getapplock @lockName, 'exclusive';";
var pLockName = new SqlParameter("@lockName", SqlDbType.NVarChar, 255);
pLockName.Value = lockName;
this.Database.ExecuteSqlCommand(sql, pLockName);
}
И позвоните сразу после начала транзакции.
public void PaidOrder(string paymentCode)
{
using (MyEntities db = new MyEntities())
{
using (DbContextTransaction trans = db.Database.BeginTransaction())
{
db.GetAppLock("PaidOrder");
Order_Payment_Code payment = db.Order_Payment_Code.Where(item => item.PaymentCode == paymentCode).FirstOrDefault();
if(payment.Status == PaymentStatus.NotPaid)
{
//This Scope can be executed multiple times
payment.Status = PaymentStatus.Paid;
db.Entry(payment).State = EntityState.Modified;
db.SaveChanges();
//Continue processing Order
}
trans.Commit();
}
}
}
Тогда одновременно может выполняться только один экземпляр этой транзакции, даже если у вас несколько интерфейсных серверов.Так что это похоже на Mutex, который работает на всех клиентах, которые обращаются к одной и той же базе данных.