我使用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);
}
为什么呢? :(
答案 0 :(得分:15)
因为实体框架只跟踪数据是否被修改,而不是跟它的原始内容不同。
当实体未更改时,我们使用一种漂亮的方法将状态重置为未修改:
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+没有问题,我已经自己做了,但我现在找不到代码。
答案 1 :(得分:3)
提示的Thx:)
这是我的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);
}
答案 2 :(得分:0)
根据User1481065的回答,如果OriginalValues
中的任何一个为空,则克服异常的可能性,请尝试以下操作。我假设一个上下文可能包含多个可能有更新的实体(可能不一定是值的实际更改)。
_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
。