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

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

我上课了

[Serializable] public class Project { public int Id { get; set; } public String Name { get; set; } //navigational fields.. public virtual List 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 Projects { get; set; } } 

所以在某个地方,我已经配置了多对多的关系,而不是像这样的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的对象即ie

 public Project Clone(Project source) { Project target = new Project(); target.Name = source.Name; //1. // target = source; //2. target.BusinessRequirements = new List(); foreach(BusinessRequirement br in source.BusinessRequirements) { BusinessRequirement nbr = DataLayer.Get(s=>s.Id=br.Id).SingleOrDefault(); if(nbr!=null) target.BusinessRequirements.Add(nbr); } //3. //target.BusinessRequirements = source.BusinessRequirements; //4. //target.BusinessRequirements = new List(); //foreach(BusinessRequirement br in source.BusinessRequirements) //{ // BusinessRequirement nbr = br; // if(nbr!=null) // target.BusinessRequirements.Add(nbr); //} return target; } 

这四种方法都不能正常工作。

最接近工作的是2,但奇怪的事情发生了。 现在,如果我向Original Project添加任何BusinessRequirements,它也会被添加到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(); foreach(BusinessRequirement br in source.BusinessRequirements) { BusinessRequirement obr = DataLayer.Get(s=>s.Id=br.Id).SingleOrDefault(); BusinessRequirement obr = new BuisnessRequirment(); if(nbr!=null){ //copy protperies in obr to nbr } target.BusinessRequirements.Add(nbr); }