【问题标题】:Cloning Object with many-to-many relationship in EntityFramework在 EntityFramework 中克隆具有多对多关系的对象
【发布时间】:2013-01-25 05:57:49
【问题描述】:

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

我有课

[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 会有这样的行为???。我错过了什么?请帮忙..

已经快一天了,但我无法让它工作。

我尝试过thisthisthisthis,但它们也没有用..

【问题讨论】:

    标签: c# linq clone entity-framework-5


    【解决方案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); 将项目及其附属子对象视为全新的。

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

    【讨论】:

      【解决方案2】:

      由于您复制 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);
               }  
      

      【讨论】:

        猜你喜欢
        • 2016-07-17
        • 2016-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多