如何深度复制实体
本文关键字:复制 实体 深度 何深度 | 更新日期: 2023-09-27 18:21:22
我在这里找到了这个片段:
public static T DeepClone<T>(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>(Entity);
db.Entities.AddObject(newEntity);
db.SaveChanges();
IT可以工作,但仍然不会复制任何嵌套的''相关记录。我在这里做错了什么?
我有这样的结构实体->ChildEntity->ChildChildEntity
->-一对多
所以我假设当我复制实体时,它也会复制所有的子记录。
更新:经过建议,我这样做了:
Entity newEntity = new Entity();
Eneity Entity = db.Include("ChildEntity").Where(p=>p.Id==Id).Single();
newEntity = DeepClone<Entity>(Entity);
db.Detach(myEntity);
myEntity.EntityKEy = null;
db.Entities.AddObject(newEntity);
db.SaveChanges();
在AddObject行上获取异常:
ObjectStateManager中已存在具有相同键的对象。ObjectStateManager无法跟踪具有相同属性的多个对象钥匙
重要的一点是,在分离之前,必须加载相关实体并创建深度克隆。如果分离实体,所有关系都会被静默地删除,因为Detach
方法仅适用于单个实体,而实体图不能同时由附加和分离的实体组成。这就是为什么需要序列化而不是简单地调用Detach
的原因。
不要忘记关闭延迟加载,否则序列化也会从数据库中提取其他导航属性的数据。还要记住,这个深度复制将创建图中所有实体的新版本,因此添加根实体也将添加所有相关实体。
所有子对象的EntityKey也会被克隆,因此在尝试使用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>(Entity);
db.Detach(myEntity);
db.SaveChanges();
myEntity.EntityKEy = null;
db.Entities.AddObject(newEntity);
db.SaveChanges();