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 ループが繰り返される回数だけカウントが減少します)。

しかし、2 回目の試行では依然として例外がスローされ、重複した PK について泣き言を言います。

エンティティを分離することは、そもそもコンテキストにない場合と同じだと思いました。他に何かする必要がありますか?

ありがとう。

4

2 に答える 2

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 に答える
1

Deatch変更を完全に元に戻すわけではありません。msdn doc によると、「エンティティのみが削除されます。同じ 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 に答える