2012-03-02 45 views
4

我正在寻找在使用实体框架时处理并发的最佳方式。最简单和最值得推荐的(也堆栈)解决方案说明如下: http://msdn.microsoft.com/en-us/library/bb399228.aspx 它看起来像:在实体框架中处理并发性

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?

编辑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如何刷新()的作品。它是否刷新整个上下文?如果是,为什么需要额外的参数(实体对象)?还是只刷新指定的对象? 例如,在这种情况下,我应该为刷新()第二个参数进行传递:

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)是不好的做法。我很惊讶在官方文档中看到这一点。 – 2012-03-02 14:05:10

+1

Re:你的改变,看起来不错。如果说100次重试无法补救这种情况,我会小心谨慎,这可能会打破循环。总是很难调试以永无止境的循环结束的问题。即使他们不应该发生;-) – 2012-03-02 14:42:32

+1

尝试在这个链接的方法它使用不同的方式来处理concurreny,这可能是更可靠的评价遵循: - http://www.asp.net/mvc/tutorials /工具入门与 - EF-使用-MVC /处理并发与 - 的实体框架式-AN-ASP净MVC应用程序 – 2012-03-16 03:38:19

回答

4

是,即使第二保存,如果可能引起OptimisticConcurrencyException - 就像你说的 - 这是Refresh()SaveChanges()之间变化。

给出的例子只是一个非常简单的重试逻辑,如果您需要重试多次或以更复杂的方式解决冲突,最好创建一个将重试n次的循环,而不是嵌套try /赶上更多的这个单一的水平。