Entity Framework 5 - Why is Entity State “Modified” after PropertyValue is set back to Original

后端 未结 3 1880
长发绾君心
长发绾君心 2021-01-11 23:59

i use the EF5 and don\'t know why a entity has the state \"modified\" after i set the only changed PropertyValue of this entity back to the original value.

         


        
相关标签:
3条回答
  • 2021-01-12 00:29

    Because Entity Framework only keeps track if the data got modified, not if it's different from it's original content.

    We use a nifty method to reset the state to unmodified when the entity is unchanged:

        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);
                }
            }
        }
    

    Please note that this method is for EF 4.0, not for the newer versions with DbContext. But it is no problem to rewrite it to use EF 4.1+, I have done this myself already but I can't find the code right now.

    0 讨论(0)
  • 2021-01-12 00:33

    Building on User1481065's answer, to overcome the possibility of an exception if any of OriginalValues is null, try the below. I've assumed a context that may contain more than one entity that may have updates (which may not necessarily be actual changes in value).

    _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
    

    You may not need the loop and therefore the presetting of _dirty.

    0 讨论(0)
  • 2021-01-12 00:38

    Thx for the hint :)

    here is my EF5 (DbContext) Solution. I call this method for every DbEnityEntry that i get from ChangeTracker.Entries()

        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);
        }
    
    0 讨论(0)
提交回复
热议问题