5

エンティティオブジェクトのグラフを切り離してから、それを新しいコンテキストにアタッチするために、次のことを試みました。

// create a context
var ctx = new TestEntities();
var parents = ctx.Parents;

// populate the graph
var newParent = new Parent {Nb = 1, Title = "Parent1"};
parents.AddObject(newParent);
newParent.Children.Add(new Child {Nb = 1, Title = "Child1"});

// put all entity objects in Unchanged state before detaching
ctx.SaveChanges(); 

// detach all entity objects
foreach (var objectStateEntry in ctx.ObjectStateManager.GetObjectStateEntries(~EntityState.Detached))
    ctx.Detach(objectStateEntry.Entity);

// create a new context
ctx = new TestEntities(); 

// attach graphs to new context
foreach (var p in parents)
    ctx.Attach(p);

このアプローチには2つの問題があります。

  1. すべてのエンティティオブジェクトをデタッチした後、newParent.Children空になります
  2. 「エンティティオブジェクトはIEntityChangeTrackerの複数のインスタンスで参照できません」と再接続すると、InvalidOperationExceptionが発生します。

ObjectContextからグラフを適切にデタッチし、別のグラフに再アタッチする方法を知っている人はいますか?

アップデート:

幸いなことに、同じObjectContext内で基になるデータベース接続を変更する方法を理解したので、これ以上デタッチ/アタッチする必要はありません。興味のある方は、次のようにしてください(ここでは、SQLiteを使用してデータベースファイルを変更します)。

var sc = ((EntityConnection)ctx.Connection).StoreConnection;
sc.ConnectionString = @"Data Source=" + newFile + ";";

Ladislavの答えは正しいと思われるので受け入れ、質問されたとおりに私の質問に答えます。

4

1 に答える 1

3

グラフ全体のディープクローンを作成し、それを別のコンテキストにアタッチする必要があります。ディープクローンは、シリアル化によって作成されます。一般的なアプローチは、以下を使用することDataContractSerializerです。

var serializer = new DataContractSerializer(typeof(Parent));
serializer.WriteObject(stream, attachedEntity);
stream.Seek(0, SeekOrgin.Begin);
detachedEntity = (Parent)serializer.ReadObject(stream);

これを機能させるには、エンティティに循環参照が含まれていてはなりません(親には子へのナビゲーションプロパティがあり、子には親へのナビゲーションプロパティがあります)。または、エンティティの属性を使用DataContract(IsReference=true)DataMemberて、循環参照の問題を解決するために参照を追跡する必要があることをシリアライザに通知する必要があります。

于 2012-07-22T10:59:49.843 に答える