c# – Entity Framework 6深度复制/克隆具有动态深度的实体

前端之家收集整理的这篇文章主要介绍了c# – Entity Framework 6深度复制/克隆具有动态深度的实体前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试深度克隆/复制包含相同类型的子项目的实体项目. Item也有参数,也应该克隆.但是,ItemType应保留为对现有ItemType的引用.

插图图:

在Stackoverflow(Entity Framework 5 deep copy/clone of an entity)的帮助下,我提出了以下相当糟糕的尝试:

  1. public Item DeepCloneItem(Item item)
  2. {
  3. Item itemClone = db.Items //Level 1
  4. .Include(i => i.ChildrenItems.Select(c => c.ChildrenItems )) //3 Levels
  5. .Include(i => i.Parameters) //Level 1 Params
  6. .Include(i => i.ChildrenItems.Select(c => c.Parameters)) //Level 2 Params
  7. .Include(i => i.ChildrenItems.Select(c => c.ChildrenItems
  8. .Select(cc => cc.Parameters))) //Level 3 Params
  9. .AsNoTracking()
  10. .FirstOrDefault(i => i.ItemID == item.ItemID);
  11. db.Items.Add(itemClone);
  12. db.SaveChanges();
  13. return itemClone;
  14. }

对于固定的深度等级3,这种尝试就像一个魅力.但是,正如您所看到的,对于每个更深层次而言,这并不是很好.该设计允许无限数量的嵌套(但在我的上下文中,不应超过5个级别).

是否有可能根据最大深度动态添加包含到IQueryable?

这是要克隆的Item-entity:

  1. public class Item
  2. {
  3. public int ItemID { get; set; }
  4.  
  5. public int? ParentItemID { get; set; }
  6. [ForeignKey("ParentItemID")]
  7. public virtual Item ParentItem { get; set; }
  8. public virtual ICollection<Item> ChildrenItems { get; set; }
  9.  
  10. [InverseProperty("Item")]
  11. public virtual ICollection<Parameter> Parameters { get; set; }
  12.  
  13. public ItemTypeIds ItemTypeID { get; set; }
  14. [ForeignKey("ItemTypeID")]
  15. public virtual ItemType ItemType { get; set; }
  16. }

解决方法

我找到了一个更通用的方法解决这个问题.
对于任何可能遇到类似问题的人,以下是我现在解决的问题:
  1. public Item DeepCloneItem(Item item)
  2. {
  3. Item itemClone = db.Items.FirstOrDefault(i => i.ItemID == item.ItemID);
  4. deepClone(itemClone);
  5. db.SaveChanges();
  6. return itemClone;
  7. }
  8.  
  9. private void deepClone(Item itemClone)
  10. {
  11. foreach (Item child in itemClone.ChildrenItems)
  12. {
  13. deepClone(child);
  14. }
  15. foreach(Parameter param in itemClone.Parameters)
  16. {
  17. db.Entry(param).State = EntityState.Added;
  18. }
  19. db.Entry(itemClone).State = EntityState.Added;
  20. }

请记住,递归调用必须在EntityState.Added分配之前.另外,递归将停在第二级.
此外,递归方法必须在实体处于附加状态时调用.否则,递归也将停止在第二级.

如果实体树非常深,请考虑使用迭代方法替换递归.有关更多信息,请查看:Wikipedia Recursion versus iteration

欢迎提供反馈和改进!

猜你在找的C#相关文章