我的课程(和表格):
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;}
}
我需要更新我的 D 对象。我使用依赖注入,所以我可以在控制器中使用存储库:
A aObj = aService.GetAById(id);
B bObj = bService.GetBByName(name);
D dObj = new D()
{
Title = "MyTitle",
AField = aObj,
BField = bObj
};
dService.Update(dObj);
在每个类库中,我只是将上下文创建为私有字段:
private MyContext db = new MyContext();
我在每个方法中使用它,如:
var model = db.A.Where(x=>x.Id == id);
return model;
但它无法正常工作,因为 A 和 B 这两个类都有 C 类的字段,所以我仍然有例外:当我调用dService.Update(dObj)
(第二个列表)时,IEntityChangeTracker的多个实例不能引用实体对象。
我发现我应该在每个repositroy中的每个方法中分离上下文,如下所示:
var model = db.A.Where(x=>x.Id == id);
db.Entry(model).State = System.Data.Entity.EntityState.Detached;
return model;
异常消失但现在aObj
和bObj
中的CField始终为空,dObj.BField
未更新。
我该如何解决这个问题以及我做错了什么?我失去了几天找到我应该做的事情:我甚至尝试删除存储库中的私有上下文字段,并且在每个方法中只使用using(var db = new MyContext())
但是然后异常“实体对象不能被IEntityChangeTracker的多个实例引用”是回来。
答案 0 :(得分:1)
您不能在EF中混合来自不同上下文的实体。请改用ids。
更新型号:
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;}
}
在控制器中:
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);