2013-02-09 75 views
2

我只想創建一個對象的精確副本。在EntityFramework中使用多對多關係克隆對象

我有一個類

[Serializable] 
public class Project 
{ 
    public int Id { get; set; } 
    public String Name { get; set; } 

    //navigational fields.. 
    public virtual List<BusinessRequirement> BusinessRequirements { get; set; } 
} 

和另一

[Serializable] 
public class BusinessRequirement 
{ 
    public int Id { get; set; } 
    public String Name { get; set; } 
    public String Description { get; set; } 
    public virtual List<Project> Projects { get; set; } 
} 

這樣的地方我已配置的B/W ProjectBusinessRequirement這樣的許多一對多的關係:

HasMany(s => s.BusinessRequirements) 
      .WithMany(s => s.Projects) 
      .Map(m => 
      { 
        m.MapLeftKey("ProjectId"); 
        m.MapRightKey("BusinessRequirementId"); 
        m.ToTable("ProjectBusinessRequirementMapping"); 

      }); 

而且我也使我的dbcontext靜態,即

public static class DataLayer 
{ 
    public static MyDbContext db; 
} 

現在,所有的M做的是,努力使Project

public Project Clone(Project source) 
{ 

    Project target = new Project(); 
    target.Name = source.Name; 
    //1. 
    // target = source;  

    //2. 
    target.BusinessRequirements = new List<BusinessRequirement>(); 
    foreach(BusinessRequirement br in source.BusinessRequirements) 
    { 
     BusinessRequirement nbr = DataLayer.Get<BusinessRequirement>(s=>s.Id=br.Id).SingleOrDefault(); 
     if(nbr!=null) 
      target.BusinessRequirements.Add(nbr); 
    } 


    //3. 
    //target.BusinessRequirements = source.BusinessRequirements; 

    //4. 
    //target.BusinessRequirements = new List<BusinessRequirement>(); 
    //foreach(BusinessRequirement br in source.BusinessRequirements) 
    //{ 
    // BusinessRequirement nbr = br; 
    // if(nbr!=null) 
    //  target.BusinessRequirements.Add(nbr); 
    //} 

     return target; 
} 

這四種方法的對象的副本正常工作。

最接近工作的是2,但是會發生一件奇怪的事情。 現在,如果我將任何BusinessRequirements添加到Original Project,它也會被添加到Clonned One,反之亦然,刪除也是如此。

不知何故,實體框架將兩個項目視爲一體。儘管這種行爲只發生在多對多的相關導航屬性中。

爲什麼EntityFramework的行爲是這樣的???。我錯過了什麼?請幫忙..

它已經差不多一天了,但我無法完成它的工作。

我已經試過thisthisthisthis但他們並沒有因爲要複製的BusinessRequirement的方式工作,要麼..

回答

1

您可以使用一個事實,即添加對象的情況下在其對象圖的任何子對象的狀態變爲Added

Project proj; 
using (var db = new MyDbContext()) 
{ 
    // Fetch a detached project and populate its BusinessRequirements. 
    proj = db.Projects.AsNoTracking().Include(p => p.BusinessRequirements) 
      .First(p => p.Id == source.Id); 
    db.Projects.Add(proj); 
    db.SaveChanges(); 
} 

通過與AsNoTracking上下文不取源項目不會將其添加到其更改跟蹤器中,並且下一行db.Projects.Add(proj);將該項目及其堅持的子對象視爲全新的。

無聲無息地,我放棄了使用一個靜態上下文的策略。這是一個不同的話題,但你不應該那樣做。環境應該有一個短暫的壽命。

0

問題的存在。您只是將源的引用添加到目標。因此,每項業務需求最終都會引用這兩個項目。

你需要做這樣的事情。

target.BusinessRequirements = new List<BusinessRequirement>(); 
     foreach(BusinessRequirement br in source.BusinessRequirements) 
     { 
      BusinessRequirement obr = DataLayer.Get<BusinessRequirement>(s=>s.Id=br.Id).SingleOrDefault(); 
BusinessRequirement obr = new BuisnessRequirment(); 
      if(nbr!=null){ 
//copy protperies in obr to nbr 
} 
       target.BusinessRequirements.Add(nbr); 
     }