[英]Handle race condition
我正在使用ASP.NET MVC和Entity Framework(版本5)開發財務應用程序。
在我的應用程序中,用戶可以批准或拒絕交易。 如果用戶批准,將轉移資金並批准通知電子郵件,否則將發送拒絕通知電子郵件。
我關心的是 ,如果兩個用戶同時批准同一個交易。 用戶將獲得事務狀態“WaitForApprove”並進行雙重轉移(如果兩個用戶都批准)。
我如何處理這種情況 ,什么是最好的解決方案(理智和低資源消耗)。
我做了一些研究,我發現Mutex可以解決這個問題。 但我不確定這是最好的解決方案。
這是我的原始代碼看起來像(Mutex未應用)。
public void TransactionApproval(int sysTransferInfoID, string username, string command)
{
// Get the transaction.
var info = _transInfoRepo.GetSingle(i => i.SYS_TRANSFER_INFO_ID == sysTransferInfoID);
if (info.SYS_TRANSFER_STATE_ID != (int)eTransferState.WaitForApprove) // Check status.
{
if (command == "Approve")
{
// Call another service to make transfer here.
// Sent approve fund transfer notification email to other users.
info.SYS_TRANSFER_STATE_ID = (int)eTranferState.Approved; // Change status.
info.APPROVE_BY = username;
}
else if (command == "Reject")
{
// Sent reject fund transfer notification email to other users.
info.SYS_TRANSFER_STATE_ID = (int)eTranferState.Rejected; // Change status.
info.APPROVE_BY = username;
}
_context.SaveChanges();
}
else
{
throw new Exception("Cannot approve transaction.");
}
}
您需要完全分離從用戶界面轉移資金的責任。 不允許用戶界面直接設置傳輸狀態。
相反,在對象上公開方法,例如ApproveTransfer()和RejectTransfer(),它們檢查對象的當前狀態,並僅在對象處於適當狀態時執行請求的操作。
該對象還需要一種機制來確保任何對象實例都知道適當的狀態,甚至是在不同的對象實例(可能在不同的服務器上)啟動所請求的操作之后創建的狀態。 為此,您必須轉到數據庫。
在數據庫中保存該狀態的最佳策略取決於您實際執行事務的方式。
如果必須在對象上設置一個標志(可能由另一個進程選取),那么具有樂觀並發性的數據庫事務就足夠了。
如果您的對象正在啟動對其他系統的調用(可能是Web服務調用以啟動傳輸),則需要鎖定數據庫中的行(具有隔離級別可重復讀取的事務)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.