Entity Framework 6 深度复制/克隆具有动态深度的实体
Posted
技术标签:
【中文标题】Entity Framework 6 深度复制/克隆具有动态深度的实体【英文标题】:Entity Framework 6 deep copy/clone of an entity with dynamic depth 【发布时间】:2016-02-25 19:23:54 【问题描述】:我正在尝试深度克隆/复制包含相同类型子项的实体项。该项目也有参数,也应该被克隆。然而,ItemType 应该作为对现有 ItemType 的引用。
图解:
在 *** (Entity Framework 5 deep copy/clone of an entity) 的帮助下,我提出了以下相当糟糕的尝试:
public Item DeepCloneItem(Item item)
Item itemClone = db.Items //Level 1
.Include(i => i.ChildrenItems.Select(c => c.ChildrenItems )) //3 Levels
.Include(i => i.Parameters) //Level 1 Params
.Include(i => i.ChildrenItems.Select(c => c.Parameters)) //Level 2 Params
.Include(i => i.ChildrenItems.Select(c => c.ChildrenItems
.Select(cc => cc.Parameters))) //Level 3 Params
.AsNoTracking()
.FirstOrDefault(i => i.ItemID == item.ItemID);
db.Items.Add(itemClone);
db.SaveChanges();
return itemClone;
对于 3 的固定深度级别,此尝试就像一个魅力。但是,正如您所看到的,这在每个更深层次上都不是很好。该设计允许无限数量的嵌套(但在我的上下文中,不应超过 5 层)。
是否有可能根据最大深度将 Includes 动态添加到 IQueryable 中?
这是要克隆的项目实体:
public class Item
public int ItemID get; set;
public int? ParentItemID get; set;
[ForeignKey("ParentItemID")]
public virtual Item ParentItem get; set;
public virtual ICollection<Item> ChildrenItems get; set;
[InverseProperty("Item")]
public virtual ICollection<Parameter> Parameters get; set;
public ItemTypeIds ItemTypeID get; set;
[ForeignKey("ItemTypeID")]
public virtual ItemType ItemType get; set;
【问题讨论】:
【参考方案1】:我找到了一种更通用的方法来解决这个问题。 对于可能遇到类似问题的任何人,这是我现在解决的方法:
public Item DeepCloneItem(Item item)
Item itemClone = db.Items.FirstOrDefault(i => i.ItemID == item.ItemID);
deepClone(itemClone);
db.SaveChanges();
return itemClone;
private void deepClone(Item itemClone)
foreach (Item child in itemClone.ChildrenItems)
deepClone(child);
foreach(Parameter param in itemClone.Parameters)
db.Entry(param).State = EntityState.Added;
db.Entry(itemClone).State = EntityState.Added;
请记住,递归调用必须在 EntityState.Added 分配之前。否则,递归将停止在第二级。 此外,递归方法必须调用处于 Attached 状态的实体。否则,递归也将停止在第二层。
如果您的实体树非常深,请考虑用迭代方法替换递归。欲了解更多信息,请查看:Wikipedia Recursion versus iteration
欢迎反馈和改进!
【讨论】:
以上是关于Entity Framework 6 深度复制/克隆具有动态深度的实体的主要内容,如果未能解决你的问题,请参考以下文章
.NET Entity Framework 与复制的 SQL 服务器一起使用
Entity Framework Core 6.0 预览4 性能改进