4

我有一个实体框架4.0模型实现与纯POCO(没有代码生成,没有自我跟踪的实体,只是普通的旧CLR对象)。更新操作问题在实体框架4(纯POCO)

现在,这里是一些代码,我有我的UI执行UPDATE:

[HttpPost] 
public ActionResult UpdatePerson(Person person) 
{ 
    repository.Attach(person); 
    unitOfWork.Commit(); 
} 

从本质上讲,我有接受一个强类型的Person对象的操作方法,以及我需要更新这个实体。

不会出错,但也不会将更改持久保存到数据库中。 :(

当我检查EntityState在我工作的单位的 “提交”:

var entities = ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged); 

我看到我的实体,与EntityState.Unchanged

这样解释道。为什么它没有被保留我的查找,添加,删除操作工作正常(坚持正确)但更新似乎并没有工作

我找到了一些线程sayin G I需要手动设置对象的状态:

ctx.ObjectStateManager.ChangeObjectState(person, EntityState.Modified); 

是正确的吗?我会把这个逻辑放在哪里?在我的工作单位上公开作为一项操作?

显然问题是我有无变化跟踪由于使用Pure POCO(没有EntityObject派生,没有INotifyPropertyChanging实现)。

但直到现在我还没有发现它的问题。

我在做什么错了?

回答

2

那么,由于您没有任何更改跟踪等,所以在调用SaveChanges()时,EF应该有方法确定如何处理附属实体。默认情况下,EntityState不变,所以如果你想更新,你必须手动设置状态。

另一种方法是使用此Id查询Person,使用从控制器获取的数据重写属性,并调用SaveChanges()。实际上这是一种更安全的方式,因为您可以防止在用户编辑Webform时删除Person的情况;但这显然需要额外往返DB,往往不太理想。

在任何情况下,我想有一个仓库Update()方法(比Attach更具体的),这将真正重视实体,改变EntityStateModified。你的行动中仍然有相对干净的代码:

public ActionResult UpdatePerson(Person person) 
{ 
    repository.Update(person); 
    unitOfWork.Commit(); 
} 
+0

是的,我真的不想做额外的往返旅行。所以我们必须手动设置EntityState(就像我预测的那样)。很酷,谢谢。另外 - 我在想 - 有没有一种方法的“更新”方法可以足够聪明,弄清楚它是一个更新或INSERT?(即检查PersonId,如果其> 0,它是一个更新,否则一个INSERT?)或是太疯狂/可怕。如果一个方法可以处理这两种情况,那将会很好。可能? – RPM1984 2010-10-26 08:01:41

+0

据我所知,你正在谈论你要创建的'Update()'方法,所以你可以使它像你想的那样聪明;)例如,附加实体,然后检查if(Person.Id == 0){/ *将状态更改为Added * /} else {/ *将状态更改为Modified * /}'。不过,我不确定这是一个好主意。有单独的插入和更新方法通常更具可读性。你为什么要合并成一个? – Yakimych 2010-10-26 08:22:43

+0

因为我使用的是MVC,并且添加/修改Person实体的操作是相同的(HTTP POST,通过强类型对象)。所以我无法知道它是一个添加还是更新(当然,我可以通过一个额外的标志)。我同意,但我将它们分离出来,可能必须通过HTTP POST中的隐藏字段,说明它是一个添加/更新。谢谢 – RPM1984 2010-10-26 21:23:38