entity framework5 – 为什么在PropertyValue设置回Original后实体状态为“已修改”

我使用EF5,并且在我将此实体的唯一更改的PropertyValue设置回原始值之后,不知道为什么实体具有“已修改”状态。

using (TestDbContext context = new TestDbContext()) { string name = context.Person.First().Name; // count is 0 int count = context.ChangeTracker.Entries().Count(e => e.State == EntityState.Modified); // Change Value context.Person.First().Name = "Test"; // count is 1 count = context.ChangeTracker.Entries().Count(e => e.State == EntityState.Modified); // Revert Value context.Person.First().Name = name; context.ChangeTracker.DetectChanges(); // count is 1 count = context.ChangeTracker.Entries().Count(e => e.State == EntityState.Modified); } 

为什么? 🙁

因为entity framework仅跟踪数据是否被修改,而不是它与原始内容的不同。

当实体不变时,我们使用一个漂亮的方法将状态重置为未修改:

  public static void CheckIfModified(EntityObject entity, ObjectContext context) { if (entity.EntityState == EntityState.Modified) { ObjectStateEntry state = context.ObjectStateManager.GetObjectStateEntry(entity); DbDataRecord orig = state.OriginalValues; CurrentValueRecord curr = state.CurrentValues; bool changed = false; for (int i = 0; i < orig.FieldCount && !changed; ++i) { object origValue = orig.GetValue(i); object curValue = curr.GetValue(i); if (!origValue.Equals(curValue) && (!(origValue is byte[]) || !((byte[])origValue).SequenceEqual((byte[])curValue))) { changed = true; } } if (!changed) { state.ChangeState(EntityState.Unchanged); } } } 

请注意,此方法适用于EF 4.0,而不适用于具有DbContext的较新版本。 但是重写它以使用EF 4.1+没有问题,我已经自己完成了这个,但我现在找不到代码。

感谢提示:)

这是我的EF5(DbContext)解决方案。 我为来自ChangeTracker.Entries()的每个DbEnityEntry调用此方法

  private void CheckIfDifferent(DbEntityEntry entry) { if (entry.State != EntityState.Modified) return; if (entry.OriginalValues.PropertyNames.Any(propertyName => !entry.OriginalValues[propertyName].Equals(entry.CurrentValues[propertyName]))) return; (this.dbContext as IObjectContextAdapter).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity).ChangeState(EntityState.Unchanged); } 

在User1481065的答案的基础上,为了克服如果任何OriginalValues为空的exception的可能性,请尝试以下方法。 我假设一个上下文可能包含多个可能有更新的实体(可能不一定是值的实际更改)。

 _dirty = False Dim oChanges As IEnumerable(Of DbEntityEntry(Of CsSetting)) = _dbContext.ChangeTracker.Entries(Of CsSetting)().Where(Function(r) r.State <> EntityState.Unchanged) For Each c As DbEntityEntry(Of CsSetting) In oChanges _dirty = c.OriginalValues.PropertyNames.Any(Function(n) (c.OriginalValues(n) Is Nothing And c.CurrentValues(n) IsNot Nothing) OrElse (c.OriginalValues(n) IsNot Nothing AndAlso Not c.OriginalValues(n).Equals(c.CurrentValues(n)))) If _dirty Then Exit For Next c Return _dirty 

您可能不需要循环,因此需要预设_dirty