2014-07-18 24 views
10

Örnek yapısıVarlık Framework yinelenen nesne ve tüm alt özellikleri

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

Bu benim gerçek yapısı bundan daha fazla düzeylerine sahiptir ama bu başarmak için çalışıyorum açıklamak için yeterli olması gerektiğini belirtmek gerekir.

Yani ben o nesneyi Klon benim Page nesne yük ve Page yani Prop1 özelliklerine bazı küçük değişiklikler yapmak, clonedPage yapısında Yukarıdaki örnekte

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

Prop2 gayet iyi ve yeni Page eklenir veritabanına. Ancak inanıyorum ki, çocuk nesnelere ait kimlikler belirlenir ve çocuklar arasındaki ilişki her zaman bire birdir. pageFromDb özgün nesnesi, tüm yeni eklenen için yeni Section nesneler oluşturmak yerine varlık çerçevesini varlık çerçeve olarak kaybedecektir.

Bunun için bir düzeltme olması vb foreach, foreach, ve yeni kayıtları foreach nesne yaratacak sonra varlık çerçevesini takmadan önce 0 tüm kimlikleri kuracak inanıyoruz. Bir varlık çerçeve ortamında bir nesneyi klonlamak için daha kolay/daha iyi bir yol var mı?

+2

Clone yöntemi ne yapar? Derin bir kopya mı yapıyor? Kimlik Alanlarını kopyalamamanız söyler misiniz? Koleksiyonlarınız doğru olduğu sürece EF, ekleme işleminden sonra sizin için Ids'ı oluşturacaktır. – Tim

+0

@Tim Sadece 'Sayfanın nesne düzeyinde AutoMapper'ı kullanarak. –

+0

[Varlık Çerçevesi'nde verileri klonlama] olası kopyası (http://stackoverflow.com/questions/2185155/cloning-data-on-entity-framework) –

cevap

20

grafiği devam eden zaman Varlık Framework bütün bir yeni nesne grafik olarak klon tedavi etmek için, grafikteki tüm varlıklar kök varlık ele geçirildi içerikten kopuk olması gerekir.

Bu, bağlamdaki AsNoTracking yöntemini kullanarak yapılabilir. Örneğin, bu, bir sayfayı ve ilgili bölümleri grafiği veritabanından çeker ve izlemeyi kapatır. Etkili bir şekilde bu küme, bunu Page DbSet'inize ekler ve veritabanında tamamen yeni bir nesne grafiği oluşturur. Yani Buna göre yeni bir sayfa ve yeni bölüm varlıkları. Not, Clone yöntemini çağırmanıza gerek yoktur.

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

'Ek bilgiler: İlişkinin 'Section_Page_Target' rolüne çakışan değişiklikler 'Context.Section_Page' algılandı. 'Değişikliklerin izlenmemesine rağmen navigasyon özelliklerinin hala dolu olduğunu söyleyebilirim. –

+0

Hmmm sayfa klonu (AsNoTracking) kadar gariptir, içerikten tamamen kaldırılır ve dolayısıyla çakışma olamaz ... Özgün sayfayı, yukarıdaki gibi tek bir çağrıyla içeriğinize mi yüklüyorsunuz? Sayfayı yüklemekten ve klonu kaydetmekten başka, içeriğinize yönelik başka işler var mı? –

+0

Harika çalıştı! Teşekkürler... –

1

Bunu deneyin!

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