我有一个MVC项目,并为数据库使用Entity Framework Code First和POCO对象。例如:
public class ClassA
{
public int? Id {get; set;}
public string Name { get; set;}
public virtual ClassB B {get; set;}
}
public class ClassB
{
public int? Id {get;set;}
public string Description {get;set;}
}
我有一个ActionResult可以创建或编辑模型。问题是当我调用此ActionResult来更新模型,并且model.B
已更改时,关系不会保存在数据库中。当调用ActionResult来创建一个新对象时,它按预期工作。我该如何解决这个问题?
public ActionResult Save(ClassA model)
{
model.B = GetBFromDb(model.B.Id.Value);
if(ModelState.IsValid)
{
if (id.HasValue)
{
context.Entry(model).State = System.Data.EntityState.Modified;
}
else
{
context.ClassAs.Add(model);
}
context.SaveChanges();
// redirect to index etc.
}
return View("EditForm", model);
}
答案 0 :(得分:4)
我通过将ClassA
更改为ClassB
的外键并设置BId
的值来解决此问题:
public class ClassA
{
public int? Id {get; set;}
public string Name { get; set;}
public int BId {get;set;} // foreign key to B
public virtual ClassB B {get; set;}
}
为什么这个外键属性代替EF生成的外来ky?
答案 1 :(得分:2)
您不能简单地致电:
context.Entry(model).State = System.Data.EntityState.Modified;
必须首先从上下文中检索实体,以便EF可以开始跟踪它。然后,您需要在调用context.SaveChanges()
之前对该实体应用任何更改。
var entity = context.ClassAs.Find(model.Id);
// set properties you want to modify on entity
entity.Name = model.Name;
entity.ClassB = context.ClassBs.Find(model.ClassB.Id);
// other changes to entity as required...
context.SaveChanges();
这样,EF就会跟踪entity
并知道对其应用更新。
答案 2 :(得分:0)
如果您附加然后将状态设置为已修改的实体框架将发送所有属性以进行更新。您不必采用下面的水獭方法,因为这会导致整个单独的负载发生。如果你这样做,那么传递一个模型就没有意义,只有一个id然后你调用TryUpdateModel来填充表单中的属性。
就个人而言,此处修改的附件更加清晰,因为加载数据不需要完整的往返
http://geekswithblogs.net/michelotti/archive/2009/11/27/attaching-modified-entities-in-ef-4.aspx