Cloning Object with many-to-many relationship in EntityFramework

允我心安 提交于 2020-01-02 19:12:55

问题


All I want is just to create an exact copy of an object.

I have a class

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

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

and another

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

so somewhere I've configured the many-to-many relationship b/w Project and BusinessRequirement like this:

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

            });

and also I've made my dbcontext static i.e.

public static class DataLayer
{
    public static MyDbContext db;
}

now, all m doing is, trying to make a copy of an object of Project i.e.

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

none of the four methods work properly.

the one which is closest to working is 2, but a strange thing happens. Now, If i add any BusinessRequirements to Original Project, it also gets added to Clonned One and vice-versa, same goes for deletion.

Somehow, entityframework is treating both the projects as one. Though this behavior occurs only in many-to-many related navigational properties.

Why EntityFramework is behaving like this???. What am I missing? please help..

Its been almost a day, but I cannot get it to work.

I have tried this, this, this and this but they didn't work either..


回答1:


You can use the fact that adding an object to a context changes the state of any child objects in its object graph to 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();
}

By fetching the source project with AsNoTracking the context does not add it to its change tracker and the next line db.Projects.Add(proj); considers the project and its adhering child objects as brand new.

Silently, I renounced your strategy to work with one static context. It's a different topic, but you should not do that. Contexts are supposed to have a short life span.




回答2:


The problem exists due to the way you are copying the BusinessRequirement. You are just adding references from the source to the target. So each BusinessRequirement end up with a reference to both Projects.

You need to do something like this.

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


来源:https://stackoverflow.com/questions/14790012/cloning-object-with-many-to-many-relationship-in-entityframework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!