官方文档说修改实体我检索DbEntityEntry对象并使用属性函数或我将其状态设置为修改。它使用以下示例
Department dpt = context.Departments.FirstOrDefault();
DbEntityEntry entry = context.Entry(dpt);
entry.State = EntityState.Modified;
我不理解第二和第三声明的目的。如果我向框架询问第一个语句之类的实体,然后按照
修改POCOdpt.Name = "Blah"
如果我再向EF询问SaveChanges(),则实体的状态为状态(我通过快照跟踪进行猜测,这不是代理)并且更改是持久化而无需手动设置状态。我在这里错过了什么吗?
答案 0 :(得分:44)
在您的方案中,您确实无需设置状态。更改跟踪的目的是找到您已更改附加实体的值并将其置于修改状态。在分离的实体(加载的实体没有更改跟踪或在当前上下文之外创建)的情况下,手动设置状态非常重要。
答案 1 :(得分:21)
如上所述,在具有断开连接的实体的场景中,将实体的状态设置为Modified
会很有用。如果您只是附加断开连接的实体,而不是从数据库中提取实体并修改并保存它,它会将数据包保存到数据库。
但是有一个很好的理由不把状态设置为Modified
(我确定Ladislav意识到这一点,但我仍然想在这里指出它们)。
记录中的所有字段都将更新,而不仅仅是更改。有许多系统可以审核更新。更新所有字段会导致大量混乱或需要审核机制来过滤掉错误的更改。
乐观并发。由于所有字段都已更新,因此可能会导致更多冲突。如果两个用户同时更新相同的记录但不是相同的字段,则不需要发生冲突。但如果它们始终更新所有字段,则最后一个用户将始终尝试写入陈旧数据。这最多会导致乐观的并发异常,或者在最坏的情况下导致数据丢失。
无用的更新。无论如何,该实体都被标记为已修改。未更改的实体也将触发更新。如果可以打开编辑窗口以查看详细信息并由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;