如何深度复制实体

我在这里找到了这个片段:

public static T DeepClone(this T obj) { using (var ms = new MemoryStream()) { var bf = new BinaryFormatter(); bf.Serialize(ms, obj); ms.Position = 0; return (T)bf.Deserialize(ms); } } 

这说明我们可以通过这个东西对所有相关对象进行深层复制。

我正在尝试这样的副本:

 db.Detach(myEntity); myEntity.EntityKEy = null; Entity newEntity = new Entity(); newEntity = DeepClone(Entity); db.Entities.AddObject(newEntity); db.SaveChanges(); 

它可以工作,但仍然不会复制任何嵌套的\相关记录。 我在这做错了什么?

我有这个结构Entity-> ChildEntity – > ChildChildEntity
– > – 一对多
所以我假设当我复制实体时它也会复制所有子记录。

更新:建议之后,我这样做了:

 Entity newEntity = new Entity(); Eneity Entity = db.Include("ChildEntity").Where(p=>p.Id==Id).Single(); newEntity = DeepClone(Entity); db.Detach(myEntity); myEntity.EntityKEy = null; db.Entities.AddObject(newEntity); db.SaveChanges(); 

在AddObject行上获取exception:

ObjectStateManager中已存在具有相同键的对象。 ObjectStateManager无法使用相同的键跟踪多个对象。

重要的一点是,您必须在分离之前加载相关实体并创建深度克隆。 如果分离实体,则会以静默方式删除所有关系,因为Detach方法仅适用于单个实体,而实体图形不能同时包含附加实体和分离实体。 这就是为什么你需要序列化而不是简单地调用Detach

不要忘记关闭延迟加载,否则您的序列化也会从数据库中提取其他导航属性的数据。 还要记住,此深层副本将在图形中创建所有实体的新版本,因此添加根实体也将添加所有相关实体。

所有子对象的EntityKeys也被克隆,因此在尝试使用AddObject添加它们之前,需要将每个子节点的EntityKey设置为null。

 Entity oldEntity = db.Include("ChildEntity").Where(p => p.Id == Id).Single(); Entity newEntity = oldEntity.DeepClone(); // assuming you've put your DeepClone extension method in a static class so that it can be used as an extension newEntity.EntityKey = null; foreach(var childEntity in newEntity.ChildEntities) { childEntity.EntityKey = null; } db.Entities.AddObject(newEntity); db.SaveChanges(); 

如果在分离实体之前尚未加载子实体,则不会序列化它们。 确保在分离实体之前加载要进行深度克隆的所有导航属性。

编辑

急切加载必须序列化的导航属性

 var entity = db.Entities.Include("ChildEntity.ChildChildEntity") .Where(l=>l.ID == myId).Single(); 

您可能应该在尝试再次附加实体之前保存上下文

 Entity newEntity = new Entity(); Eneity Entity = db.Include("ChildEntity").Where(p=>p.Id==Id).Single(); newEntity = DeepClone(Entity); db.Detach(myEntity); db.SaveChanges(); myEntity.EntityKEy = null; db.Entities.AddObject(newEntity); db.SaveChanges();