2011-08-18 63 views
36

官方文档说修改一个实体我检索一个DbEntityEntry对象,并使用属性函数或设置其状态为修改。它使用以下示例实体框架 - 为什么显式设置实体状态为修改?

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

我不明白第二和第三条语句的目的。如果我问了框架,像第一次声明中的实体中,然后修改POCO作为

dpt.Name = "Blah" 

如果我再问问EF到的SaveChanges(),实体被修改的状态(我通过快照跟踪进行猜测,这不是代理),并且无需手动设置状态即可保持更改。我在这里错过了什么吗?

回答

38

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

+4

感谢您的确认。我读过的很多教程似乎都使用这种混淆的方法。 – SeeNoWeevil

16

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

但是可以有很好的理由不要将状态设置为Modified(我确信拉迪斯拉夫知道这一点,但我仍想在这里指出)。

  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.SetValuesModified标志着个别属性。

+0

@GertAmold,你可以说明'CurrentValues.SetValues'所在的命名空间。我可以在** ASP.NET Core 1.0 **中找到它 –

相关问题