2012-03-02 3 views
4

Я ищу лучший способ обработки параллелизма при использовании Entity Framework. Самый простой и наиболее рекомендуемый (также в стеке) решение описано здесь: http://msdn.microsoft.com/en-us/library/bb399228.aspx И это выглядит следующим образом:Обработка параллелизма в Entity Framework

try 
{ 
    // Try to save changes, which may cause a conflict. 
    int num = context.SaveChanges(); 
    Console.WriteLine("No conflicts. " + 
    num.ToString() + " updates saved."); 
} 
catch (OptimisticConcurrencyException) 
{ 
    // Resolve the concurrency conflict by refreshing the 
    // object context before re-saving changes. 
    context.Refresh(RefreshMode.ClientWins, orders); 

    // Save changes. 
    context.SaveChanges(); 
    Console.WriteLine("OptimisticConcurrencyException " 
    + "handled and changes saved"); 
} 

Но достаточно ли этого? Что делать, если что-то меняется между Refresh() и вторым SaveChanges()? Будет исключено исключение OptimisticConcurrencyException?

EDIT 2:

Я думаю, что это будет окончательное решение:

int savesCounter = 100; 
    Boolean saveSuccess = false; 
    while (!saveSuccess && savesCounter > 0) 
    { 
     savesCounter--; 
     try 
     { 
      // Try to save changes, which may cause a conflict. 
      int num = context.SaveChanges(); 
      saveSuccess = true; 
      Console.WriteLine("Save success. " + num.ToString() + " updates saved."); 
     } 
     catch (OptimisticConcurrencyException) 
     { 
      // Resolve the concurrency conflict by refreshing the 
      // object context before re-saving changes. 
      Console.WriteLine("OptimisticConcurrencyException, refreshing context."); 
      context.Refresh(RefreshMode.ClientWins, orders); 

     } 
    } 

Я не уверен, если Iunderstand как работает Refresh(). Обновляет ли он весь контекст? Если да, то почему он принимает дополнительные аргументы (объекты объектов)? Или он обновляет только указанные объекты? Например, в этой ситуации то, что должно быть передано в Refresh() второй аргумент:

Order dbOrder = dbContext.Orders.Where(x => x.ID == orderID); 
dbOrder.Name = "new name"; 
//here whole the code written above to save changes 

должно быть dbOrder?

+2

+1 Это было то же возражение против этого примера, когда я впервые его прочитал! Как правило, это плохая практика делать «рискованные» операции (saveChanges) в обработчике исключений. Я был поражен, увидев это в официальной документации. –

+1

Re: Ваше изменение, оно выглядит хорошо. Я, быть осторожным, вероятно, поставил бы способ разбить цикл, если бы 100 попыток не смогли исправить ситуацию. Всегда трудно отлаживать проблемы, которые заканчиваются бесконечными циклами. Даже если они никогда не должны произойти ;-) –

+1

Попробуйте подход в этой ссылке, он использует другой способ обработки concurreny, который может быть более надежным, чтобы следить за: - http://www.asp.net/mvc/tutorials/получение стартером-с-эф-используя-MVC/обработка-параллелизм-с-сущность-рамки-в-ан-Asp-нетто-MVC-приложений –

ответ

4

Да, даже второе сохранение может вызвать исключение OptimisticConcurrencyException, если, как вы говорите, что-то меняется между Refresh() и SaveChanges().

Приведенный пример - очень простая логика повтора, если вам нужно повторить несколько раз или разрешить конфликт более сложным образом, вам лучше создать цикл, который будет повторять n раз, чем вложенность try/ловить больше, чем этот единственный уровень.

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