【问题标题】:Entity Framework - Why explicitly set entity state to modified?实体框架 - 为什么将实体状态显式设置为已修改?
【发布时间】:2011-10-29 16:34:44
【问题描述】:

官方文档说要修改一个实体,我检索一个 DbEntityEntry 对象并使用属性函数或将其状态设置为已修改。它使用以下示例

Department dpt = context.Departments.FirstOrDefault();
DbEntityEntry entry = context.Entry(dpt);
entry.State = EntityState.Modified;

我不明白第 2 条和第 3 条语句的目的。如果我像第一个语句那样询问实体的框架,然后修改 POCO,如

dpt.Name = "Blah"

如果我随后要求 EF SaveChanges(),则实体 具有 MODIFIED 状态(我猜是通过快照跟踪,这不是代理)并且更改会在没有需要手动设置状态。我在这里遗漏了什么吗?

【问题讨论】:

    标签: entity-framework


    【解决方案1】:

    在您的场景中,您确实不必设置状态。更改跟踪的目的是发现您已更改附加实体上的值并将其置于修改状态。对于分离的实体(在没有更改跟踪的情况下加载或在当前上下文之外创建的实体),手动设置状态很重要。

    【讨论】:

    • 感谢您的确认。我读过的很多教程似乎都使用了这种令人困惑的方法。
    【解决方案2】:

    如前所述,在实体断开连接的情况下,将实体的状态设置为Modified 会很有用。如果您只是附加断开连接的实体,它会节省到数据库的往返,而不是从数据库中获取实体并修改和保存它。

    但是不将状态设置为Modified 可能有很好的理由(我相信 Ladislav 已经意识到这一点,但我仍然想在这里指出它们)。

    1. 将更新记录中的所有字段,而不仅仅是更改。有许多系统会审核更新。更新所有字段要么会导致大量混乱,要么需要审核机制过滤掉错误的更改。

    2. 乐观并发。由于所有字段都已更新,这可能会导致不必要的冲突。如果两个用户同时更新相同的记录但不同的字段,则不需要冲突。但如果他们总是更新所有字段,最后一个用户总是会尝试写入过时的数据。这充其量只会导致乐观并发异常,或者在最坏的情况下会导致数据丢失。

    3. 无用的更新。无论如何,该实体都被标记为已修改。未更改的实体也会触发更新。如果编辑窗口可以打开以查看详细信息并由OK 关闭,则很容易发生这种情况。

    所以这是一个很好的平衡。减少往返或减少冗余。

    无论如何,将状态设置为Modified 的替代方法是(使用DbContext API):

    void UpdateDepartment(Department department)
    {
        var dpt = context.Departments.Find(department.Id);
        context.Entry(dpt).CurrentValues.SetValues(department);
        context.SaveChanges();
    }
    

    CurrentValues.SetValues 将各个属性标记为 Modified

    或附加断开连接的实体并手动将单个属性标记为Modified

    context.Entry(dpt).State = System.Data.Entity.EntityState.Unchanged;
    context.Entry(dpt).Property(d => d.Name).IsModified = true;
    

    【讨论】:

    • @GertAmold,您能否说明CurrentValues.SetValues 所在的命名空间。我可以在 ASP.NET Core 1.0 中使用它
    • 如果有人必须在 ObjectSet 上执行此操作,请使用:_context.Departments.ApplyCurrentValues(department))
    • 很好的答案,您的最后一次编辑对 EFCore 5 仍然有效吗?
    • @kuldeep 是的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    相关资源
    最近更新 更多