【问题标题】:Handle concurrency in Entity Framework在实体框架中处理并发
【发布时间】:2012-03-16 11:38:19
【问题描述】:

我正在寻找在使用实体框架时处理并发的最佳方法。这里描述了最简单和最推荐的(也在堆栈上)解决方案: 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);

        }
    }

我不确定我是否理解 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吗?

【问题讨论】:

  • +1 这与我第一次阅读这个例子时的反对意见相同!通常,在异常处理程序中执行“风险”操作(saveChanges)是不好的做法。在官方文档中看到这一点我很惊讶。
  • 回复:您的更改,看起来不错。如果说 100 次重试未能纠正这种情况,我很小心可能会打破循环。总是难以调试以永无止境的循环而告终的问题。即使它们永远不应该发生;-)
  • 尝试此链接中的方法,它使用不同的方式处理并发,这可能是更可靠的方法:-asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/…

标签: entity-framework concurrency optimistic-concurrency


【解决方案1】:

是的,即使是第二次保存也可能导致 OptimisticConcurrencyException - 如您所说 - 在 Refresh()SaveChanges() 之间发生变化。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-27
    • 2011-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    相关资源
    最近更新 更多