我想要的只是创建一个对象的精确副本。
我有一个班级
[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 Project
和BusinessRequirement
,如下所示:
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,但奇怪的事情发生了。
现在,如果我向Original Project
添加任何BusinessRequirements,它也会被添加到Clonned One
,反之亦然,同样也可以删除。
不知何故,entityframework将这两个项目视为一个项目。虽然此行为仅出现在多对多相关的导航属性中。
为什么EntityFramework表现得像这样?我错过了什么?请帮忙..
差不多有一天了,但是我无法让它发挥作用。
答案 0 :(得分:2)
您可以使用以下事实:将对象添加到上下文会将其对象图中任何子对象的状态更改为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);
会将项目及其附加的子对象视为全新的。
默默地,我放弃了使用一个静态上下文的策略。这是一个不同的主题,但你不应该这样做。上下文的寿命应该很短。
答案 1 :(得分:0)
由于您复制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);
}