问题
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