在EntityFramework中克隆具有多对多关系的对象

本文关键字:关系 对象 EntityFramework | 更新日期: 2023-09-27 17:58:23

我只想创建一个对象的精确副本。

我有一个类

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

现在,我所做的就是,试图复制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会这样???。我错过了什么?请帮忙。。

已经快一天了,但我不能让它去上班。

我试过这个,这个,这个和这个,但它们也不起作用。。

在EntityFramework中克隆具有多对多关系的对象

您可以使用这样一个事实:将对象添加到上下文会将其对象图中任何子对象的状态更改为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);将该项目及其附属子对象视为全新的。

我默默地放弃了你在一个静态环境下工作的策略。这是一个不同的话题,但你不应该那样做。上下文的寿命应该很短。

问题是由于您复制BusinessRequirement的方式造成的。您只是将引用从源添加到目标。因此,每个BusinessRequirement最终都引用了这两个项目。

你需要做这样的事情。

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