10

我使用 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);
        }

为什么?:(

4

3 回答 3

17

因为实体框架只跟踪数据是否被修改,而不是与原始内容不同。

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

    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+ 是没有问题的,我自己已经这样做了,但我现在找不到代码。

于 2012-11-22T14:55:25.960 回答
5

谢谢提示:)

这是我的 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);
    }
于 2012-11-22T15:29:57.783 回答
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.

于 2017-01-14T18:09:01.387 回答