我发现的所有示例都引用了一个名为ObjectContext的类,它在CTP5中似乎不存在。我必须强调,CTP5是我第一次接触实体框架。
我有一个已连接到我的DbContext的断开连接的POCO。 SaveChanges不会接受更改,我如何告诉我的上下文更新该实体?
_context.Users.Attach(user);
// The user has been replaced.
_context.SaveChanges();
// The change is not saved.
我做错了什么?
更新12/01/2011
对大多数人来说可能是显而易见的,但作为EF的第一次使用者,我没有想到附加已经附加的对象会清除之前的状态。这给我带来了很多痛苦。但是我想以一种非常通用的方式使用Repository模式,这种方式不关心对象是否已经附加或者是作为ASP.NET MVC绑定的结果而新创建的。所以我需要一个UpdateUser
方法,我已将其附加到下面。
public User UpdateUser(User user) {
if (_context.Entry(user).State == EntityState.Detached) {
_context.Users.Attach(user);
_context.Entry(user).State = EntityState.Modified;
}
return user;
}
该方法显然假设对象以某种方式存在于数据存储中,毕竟它被称为UpdateUser
。如果对象已经附加,您将受益于对象的先前状态,这反过来将允许对数据库进行优化更新。但是,如果未附加对象,则该方法会强制整个对象变脏。
富
答案 0 :(得分:29)
当您附加实体时,它会转到 Unchanged 状态(由于它附加到上下文,因此没有更改)。您只需要将实体状态显式更改为已修改:
_context.Users.Attach(user);
_context.Entry(user).State = System.Data.Entity.EntityState.Modified;
_context.SaveChanges();
答案 1 :(得分:4)
为了完整起见,您可以通过将DbContext强制转换为IObjectContextAdapter来访问ObjectContext:
((IObjectContextAdapter)context).ObjectContext.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
Morteza的方法虽然更清洁,但我得到了投票。
答案 2 :(得分:2)
我相信你在调用修改之前不需要附加实体。只需设置为修改即可完成工作。
if (_context.Entry(user).State == EntityState.Detached)
{
_context.Entry(user).State = EntityState.Modified;
}