2015-11-23 17 views
6

Tôi đang cố gắng sao chép sâu/sao chép một mục thực thể chứa Trẻ em-Các mặt hàng cùng loại. Item cũng có các tham số, cũng cần được nhân bản. ItemType, tuy nhiên, nên được để lại như một tham chiếu đến ItemType hiện có.Entity Framework 6 bản sao sâu/bản sao của một thực thể có độ sâu động

Sơ đồ để minh hoạ: enter image description here

Với sự giúp đỡ của Stackoverflow (Entity Framework 5 deep copy/clone of an entity) Tôi đã đưa ra những nỗ lực khá tệ hại sau:

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; 
} 

Đối với một độ sâu mức cố định của 3 nỗ lực này hoạt động như một sự quyến rũ. Tuy nhiên, như bạn có thể thấy, điều này là không nhận được khá tốt đẹp với mỗi cấp độ sâu hơn. Thiết kế cho phép số lượng lồng nhau vô hạn (Trong ngữ cảnh của tôi, tuy nhiên, không nên có nhiều hơn 5 cấp).

Có khả năng tự động thêm Bao gồm vào IQueryable tùy thuộc vào độ sâu tối đa không?

Đây là item thực thể nhân bản:

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; } 
} 

Trả lời

2

Tôi đã tìm thấy một cách tiếp cận chung chung hơn cho vấn đề này. Đối với bất cứ ai có thể gặp phải một vấn đề tương tự, đây là cách tôi giải quyết nó cho bây giờ:

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; 
} 

Hãy ghi nhớ rằng các cuộc gọi đệ quy phải trước khi phân bổ EntityState.Added. Ngược lại, sự đệ quy sẽ dừng lại ở cấp độ thứ hai. Hơn nữa, phương thức đệ quy phải được gọi với một thực thể trong trạng thái đính kèm. Nếu không, đệ quy cũng sẽ dừng ở cấp độ thứ hai.

Cân nhắc thay thế đệ quy bằng cách tiếp cận lặp nếu cây thực thể của bạn rất sâu. Để biết thêm thông tin, hãy xem: Wikipedia Recursion versus iteration

Phản hồi và cải tiến chào mừng!

Các vấn đề liên quan