Luk*_*uke 7 .net c# linq entity-framework entity-framework-6
我正在尝试深度克隆/复制包含相同类型的子项目的实体项目.Item也有参数,也应该克隆.但是,ItemType应保留为对现有ItemType的引用.
在Stackoverflow(实体框架5深度复制/克隆实体)的帮助下,我提出了以下相当糟糕的尝试:
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;
}
Run Code Online (Sandbox Code Playgroud)
对于固定的深度等级3,这种尝试就像一个魅力.但是,正如您所看到的,对于每个更深层次而言,这并不是很好.该设计允许无限数量的嵌套(但在我的上下文中,不应超过5个级别).
是否有可能根据最大深度动态添加包含到IQueryable?
这是要克隆的Item-entity:
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; }
}
Run Code Online (Sandbox Code Playgroud)
我找到了解决这个问题的更通用的方法。对于可能遇到类似问题的人,我现在解决的方法如下:
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;
}
Run Code Online (Sandbox Code Playgroud)
请记住,递归调用必须在 EntityState.Added 分配之前。否则,递归将在第二层停止。此外,必须使用处于附加状态的实体来调用递归方法。否则,递归也会在第二层停止。
如果您的实体树非常深,请考虑用迭代方法替换递归。有关更多信息,请查看:维基百科递归与迭代
欢迎反馈和改进!
| 归档时间: |
|
| 查看次数: |
4684 次 |
| 最近记录: |