C#& EF 4 - 更新数据库

时间:2015-10-21 08:16:19

标签: c# asp.net-mvc entity-framework dependency-injection

我的课程(和表格):

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;

异常消失但现在aObjbObj中的CField始终为空,dObj.BField未更新。

我该如何解决这个问题以及我做错了什么?我失去了几天找到我应该做的事情:我甚至尝试删除存储库中的私有上下文字段,并且在每个方法中只使用using(var db = new MyContext())但是然后异常“实体对象不能被IEntityChangeTracker的多个实例引用”是回来。

1 个答案:

答案 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);