且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

实体框架5.0处理乐观并发异常?

更新时间:2023-02-20 12:13:44

在DbContext API中解决并发异常的方法将重新加载原始实体:

  catch(DbUpdateConcurrencyException ex)
{
//获取失败的条目
var entry = ex.Entries.Single(...);
//用数据库中的值覆盖原始值,但不要
//触摸保存更改的当前值
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
}

您还应该能够使用上述代码,但必须获得 DbContext 实例中的c $ c> ObjectContext 实例(它只是 ObjectContext 的包装

  catch(DbUpdateConcurrencyException ex)
{
var objContext =((IObjectContextAdapter)context) .ObjectContext;
//获取失败的条目
var entry = ex.Entries.Single(...);
//现在在ObjectContext上调用刷新
objContext.Refresh(RefreshMode.ClientWins,entry.Entity);
}

您甚至可以尝试:

  objContext.Refresh(RefreshMode.ClientWins,ex.Entries.Select(e => e.Entity)); 


When handling several potential exceptions during a context.SaveChanges() one of the exceptions is OptimisticConcurrency. Microsoft's documentation on this at http://msdn.microsoft.com/en-us/library/bb399228.aspx discusses this for EF 4.x ...

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");
}

... but on EF 5.0 (RC), this doesn't seem to work because Refresh() doesn't exist on my EF5, code-first, DbContext derived context class.

I do see context.Entry(context.SalesOrderHeaders).Reload(); - but that appears to be a straightup reload-from-db and not a refresh/merge (with policy client wins).

Any ideas how to handle Optimistic concurrency exceptions in EF5? Actually even general pointers on exception handling in SaveChanges() would be nice

Thanks

The way how to solve concurrency exception in DbContext API reloads original entity:

catch (DbUpdateConcurrencyException ex)
{
    // Get failed entry
    var entry = ex.Entries.Single(...);
    // Overwrite original values with values from database but don't
    // touch current values where changes are held
    entry.OriginalValues.SetValues(entry.GetDatabaseValues());
}

You should also be able to use the mentioned code but you must get ObjectContext instance from your DbContext instance (it is just a wrapper around ObjectContext).

catch (DbUpdateConcurrencyException ex)
{
    var objContext = ((IObjectContextAdapter)context).ObjectContext;
    // Get failed entry
    var entry = ex.Entries.Single(...);
    // Now call refresh on ObjectContext
    objContext.Refresh(RefreshMode.ClientWins, entry.Entity);        
}

You may even try:

objContext.Refresh(RefreshMode.ClientWins, ex.Entries.Select(e => e.Entity));