强制EF 4.1 Code First将附加实体视为已修改

时间:2010-12-10 22:28:59

标签: entity-framework code-first

我发现的所有示例都引用了一个名为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。如果对象已经附加,您将受益于对象的先前状态,这反过来将允许对数据库进行优化更新。但是,如果未附加对象,则该方法会强制整个对象变脏。

现在似乎很明显,不是之前。希望它可以帮到某人。

3 个答案:

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