0

我正在尝试处理批量插入过程中可能存在具有相同主键的实体的情况,这当然会使SaveChanges抛出异常。

这是我所拥有的:

try
{
    _context.SaveChanges();
    _context.Dispose();
    _context = null;
    _context = SelectContext<T>();
    _commitCount = 0;
}
catch (System.Data.UpdateException updateEx)
{
    //Remove from _context all the entries that errored in the SaveChange() process...
    if (updateEx.StateEntries != null)
    {
        foreach (ObjectStateEntry stateEntry in updateEx.StateEntries)
        {

            if ((System.Data.EntityState)stateEntry.Entity.GetType().GetProperty("EntityState").GetValue(stateEntry.Entity, null) != System.Data.EntityState.Detached)
            {
                _context.Detach(stateEntry.Entity);
            }
         }

}

//Save context changes again this time without erroneous entries...
try
{
     _context.SaveChanges();
     _context.Dispose();
     _context = null;
     _context = SelectContext<T>();
     _commitCount = 0;
 }
 catch (Exception ex)
 {                  
   //Welp, at the point, I'm clueless...
 }

如果我查看 ObjectStateManager,实体确实被删除了(计数随着 foreach 循环的迭代次数而下降。)

但它仍然在第二次尝试时抛出异常,抱怨欺骗 PK。

我认为分离一个实体是一样的,如果它从一开始就没有出现在上下文中。我需要做其他事情吗?

谢谢。

4

2 回答 2

1

Deatch不会完全撤消更改。根据 msdn 文档“仅删除实体;如果同一 ObjectStateManager 正在跟踪任何相关对象,则不会自动分离这些对象。”

仅删除您传递给分离的实体。其他更改将导致失败。你的分贝会有争用吗?如果这个应用程序是唯一对数据库进行更改的东西,那么您可以撤消更改,context.Refresh(RefreshMode.StoreWins, object);否则它会更复杂一些。

你必须做这样的事情;

 var entry = context.ObjectStateManager.GetObjectStateEntry(((IEntityWithKey)object).EntityKey);

  for (int i = 0; i < entry.OriginalValues.FieldCount; i++)

{

     entry.CurrentValues.SetValue(i, entry.OriginalValues[i]);

}

entry.AcceptChanges();

上面的代码使用 将ObjectSateManager所有修改的对象返回到它们的原始状态,之后context.SaveChanges();应该成功。

您可能还会发现这个有用http://dotnetadventurer.blogspot.com/2010/09/discarding-changes-to-objectcontext-in.html我没有尝试过他的代码,我通常以不同的方式初始化我的上下文,所以我不是确定它是否适用于您的示例,但它非常简单,所以如果可以,这就是我要走的路线。

于 2012-11-30T23:05:33.200 回答
1

这就是我最终在我的情况下所做的:

_context.ObjectStateManager.ChangeObjectState(stateEntry.Entity, System.Data.EntityState.Unchanged);
_context.ApplyOriginalValues<T>(entityType, (T)stateEntry.Entity);
_context.Detach(stateEntry.Entity);

之后,我可以保存上下文更改。

于 2012-12-03T15:17:52.637 回答