Reputation: 5717
My classes (and tables):
class A {
public int Id {get; set;}
public string Name {get; set;}
public virtual C CField {get; set;}
}
class B {
public int Id {get; set;}
public string Name {get; set;}
public DateTime Date {get; set;}
public virtual C CField {get; set;}
}
class C {
public int Id {get; set;}
public string Name {get; set;}
}
class D {
public int Id {get; set;}
public string Title {get; set;}
public virtual A AField {get; set;}
public virtual B BField {get; set;}
}
I need update my D object. I use dependency injection so I can use repositories in controller:
A aObj = aService.GetAById(id);
B bObj = bService.GetBByName(name);
D dObj = new D()
{
Title = "MyTitle",
AField = aObj,
BField = bObj
};
dService.Update(dObj);
In each class repository I just create context as private field:
private MyContext db = new MyContext();
and I use it in every method like:
var model = db.A.Where(x=>x.Id == id);
return model;
But it can't work because both classes A and B has field with C class so I still got excepted: An entity object cannot be referenced by multiple instances of IEntityChangeTracker when I call dService.Update(dObj)
(second listing).
I found that I should detach context in every method in each repositroy like this:
var model = db.A.Where(x=>x.Id == id);
db.Entry(model).State = System.Data.Entity.EntityState.Detached;
return model;
Exception was gone but now CField in aObj
and bObj
is always null and dObj.BField
is not updated.
How can I fix that and what I'm doing wrong? I lost a few days for finding out what I should do: I even try remove private context field in repositories and in every method just use using(var db = new MyContext())
but then exception "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" is back.
Upvotes: 0
Views: 92
Reputation: 120
You can't mix entities from different contexts in EF. Use ids instead.
Update models:
class A {
public int Id {get; set;}
public string Name {get; set;}
public int CFieldId {get; set;}
public virtual C CField {get; set;}
}
class B {
public int Id {get; set;}
public string Name {get; set;}
public DateTime Date {get; set;}
public int CFieldId {get; set;}
public virtual C CField {get; set;}
}
class C {
public int Id {get; set;}
public string Name {get; set;}
}
class D {
public int Id {get; set;}
public string Title {get; set;}
public int AFieldId {get; set;}
public int BFieldId {get; set;}
public virtual A AField {get; set;}
public virtual B BField {get; set;}
}
And in controller:
A aObj = aService.GetAById(id);
B bObj = bService.GetBByName(name);
D dObj = new D()
{
Title = "MyTitle",
AFieldId = aObj.Id,
BFieldId = bObj.Id
};
dService.Update(dObj);
Upvotes: 1