2014-10-10 2 views
1

Я занимаюсь разработкой финансового приложения с помощью 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."); 
    } 
} 
+0

Вы просматривали тип данных SQL Server ['ROWVERSION'] (http://msdn.microsoft.com/en-gb/library/ms182776.aspx)? – DavidG

+1

Используйте транзакцию базы данных, возможно, с оптимистичным параллелизмом. – Joe

+0

Если вы следуете рекомендациям использовать состояние хранимой базы данных для своей транзакции (и это хорошо, обычные рекомендации), вы можете не использовать EF для нее. Хотя у него, вероятно, есть обертки вокруг уровней изоляции, выяснение оберток может быть более жестким, чем на самом деле просто вызов хранимой процедуры, которую вы пишете сами (в зависимости от вашего знакомства с EF, я думаю). – welegan

ответ

3

Вам необходимо отделить ответственность за перевод денег из пользовательского интерфейса полностью. Не позволяйте пользовательскому интерфейсу напрямую устанавливать состояние передачи.

Вместо этого подвергать методы объекта, такие как ApproveTransfer() и RejectTransfer(), которые проверяют текущее состояние объекта и только выполнить предложено действия, если объект находится в соответствующем состоянии.

Объект также нуждается в механизме для обеспечения того, чтобы соответствующее состояние было известно любому экземпляру объекта, даже созданному после запуска запрошенного действия в другом экземпляре объекта, возможно, на другом сервере. Для этого необходимо обратиться к базе данных.

Лучшая стратегия для хранения этого состояния в базе данных зависит от того, как вы фактически выполняете транзакцию.

Если вы должны просто установить флаг на объекте (который, возможно, подхвачен другим процессом), транзакция базы данных с оптимистичным параллелизмом, вероятно, будет достаточной.

Если ваш объект инициирует вызовы в другие системы (возможно, вызов веб-службы для инициирования передачи), вам необходимо заблокировать строку в базе данных (транзакция с isolation level repeatable read).

Смежные вопросы