2014-07-18 14 views
10
cấu trúc

Ví dụkhung Entity trùng lặp đối tượng và tất cả các thuộc tính con

public class Page 
{ 
    public int PageId { get; set; } 
    public string Prop1 { get; set; } 
    public string Prop2 { get; set; } 
    public virtual List<Section> Sections { get; set; } 
} 

public class Section 
{ 
    public int SectionId { get; set; } 
    public int PageId { get; set; } 
    public virtual Page Page { get; set; } 
    public virtual List<Heading> Headings { get; set; } 
} 

public class Heading 
{ 
    public int HeadingId { get; set; } 
    public int SectionId { get; set; } 
    public virtual Section Section { get; set; } 
} 

Nó đáng chú ý là cấu trúc thực tế của tôi có mức hơn này, nhưng điều này là đủ để giải thích những gì tôi đang cố gắng để đạt được.

Vì vậy, tôi nạp đối tượng Page của tôi sau đó tôi Clone đối tượng đó và thực hiện một số thay đổi nhỏ để các thuộc tính của Page tức Prop1, Prop2

Page pageFromDb = getPageMethod(); 
Page clonedPage = pageFromDb.Clone(); 
clonedPage.Prop1 = clonedPage.Prop1 + " Cloned"; 
addPageMethod(clonedPage); //Adds the page to db 

Trong ví dụ trên clonedPage cấu trúc là tốt và mới Page được thêm vào cơ sở dữ liệu. Tuy nhiên tôi tin rằng bởi vì các Id của các đối tượng trẻ em được thiết lập và mối quan hệ của trẻ em luôn luôn là một đến nhiều. Đối tượng gốc pageFromDb sẽ mất tất cả các đối tượng con là khung thực thể thay vì tạo đối tượng Section mới cho nhân bản Page sẽ cập nhật Section.PageId vào trang vừa được chèn.

Tôi tin rằng một sửa chữa cho điều này sẽ được foreach, foreach, vv và đặt tất cả của Id để 0 trước khi chèn sau đó khuôn khổ tổ chức sẽ tạo ra kỷ lục mới đối tượng foreach. Có cách nào dễ dàng hơn/tốt hơn để sao chép một đối tượng trong môi trường khung thực thể.

+2

Phương pháp Clone làm gì? Nó đang làm một bản sao sâu? Bạn có thể yêu cầu không sao chép các Trường Id không? Miễn là các bộ sưu tập của bạn là đúng, EF sẽ xây dựng các Id cho bạn sau khi chèn. – Tim

+0

@Tim Chỉ cần sử dụng AutoMapper ở cấp đối tượng 'Trang' hàng đầu. –

+0

bản sao có thể có của [Nhân bản dữ liệu trên khung thực thể] (http://stackoverflow.com/questions/2185155/cloning-data-on-entity-framework) –

Trả lời

20

Để Khung thực thể xử lý bản sao làm toàn bộ biểu đồ đối tượng mới khi vẫn tồn tại biểu đồ, tất cả các thực thể trong biểu đồ cần phải được ngắt kết nối từ ngữ cảnh mà thực thể gốc được truy lục.

Điều này có thể được thực hiện bằng phương pháp AsNoTracking trong ngữ cảnh.

Ví dụ: thao tác này sẽ kéo một trang và biểu đồ các phần liên quan từ cơ sở dữ liệu và tắt theo dõi. Có hiệu quả đây là một bản sao như thể bạn thêm điều này vào Trang DbSet của bạn và lưu nó sẽ tạo ra một đồ thị đối tượng hoàn toàn mới trong cơ sở dữ liệu. I E. một thực thể Trang mới và các thực thể Phần mới tương ứng. Lưu ý, bạn sẽ không cần gọi phương thức Clone của mình.

var clone = context.Pages 
    .AsNoTracking() 
    .Including(pages => pages.Sections) 
    .Single(...); 
context.Pages.Add(clone); 
context.SaveChanges(); // creates an entirely new object graph in the database 
+0

'Thông tin bổ sung: Thay đổi mâu thuẫn với vai trò 'Section_Page_Target' của mối quan hệ 'Context.Section_Page' đã được phát hiện.' Tôi sẽ đề xuất rằng mặc dù các thay đổi không được theo dõi các thuộc tính điều hướng vẫn được phổ biến. –

+0

Hmmm thats lạ như clone trang (AsNoTracking) là hoàn toàn loại bỏ khỏi bối cảnh và do đó không thể xung đột ... Bạn đang tải trang gốc với một cuộc gọi duy nhất để bối cảnh của bạn như trên? Bất kỳ công việc nào khác đang diễn ra đối với bối cảnh của bạn ngoài việc tải trang và lưu bản sao? –

+0

Đã làm việc tuyệt vời! Cảm ơn... –

1

Hãy thử cái này!

public Page CopyPage(int pageID) 
{ 
    using(Context context = new Context()) 
    { 
     context.Configuration.LazyLoadingEnabled = false; 
     Page dbPage = context.Pages.Where(p => p.PageId == pageID).Include(s => s.Sections.Select(s => s.Section)).First(); 
     Page page = dbPage.Clone(); 
     page.PageId = 0; 

     for (int i = 0; i < dbPage .Sections.Count; i++) 
      page.Sections[i] = new Section 
      { 
       SectionId = 0, 
       PageId = 0, 
       Page = null, 
       Headings = dbPage[i].Headings 
      }; 
     return page; 
    } 
} 

public Page Clone() 
    { 
     Object page = this.GetType().InvokeMember("", BindingFlags.CreateInstance, null, this, null); 

     foreach(PropertyInfo propertyInfo in this.GetType().GetProperties()) 
     { 
      if(propertyInfo.CanWrite) 
      { 
       propertyInfo.SetValue(page, propertyInfo.GetValue(this, null), null); 
      } 
     } 

     return page; 
    } 
Các vấn đề liên quan