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..
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.
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