5
\$\begingroup\$

The entity framework will only save properties it detects has changed via its proxy classes. I have a situation where I want a property to always be saved no matter if it changed or not.

I wrote a blank attribute called AlwaysUpdate which I apply to the property. I then overrode SaveChanges to scan for these attributes and mark the field as Modified. Is this code all right?

public override int SaveChanges()
{
    var changeSet = ChangeTracker.Entries();
    if (changeSet != null)
    {
        foreach (var entry in changeSet.Where( c=> c.State == System.Data.EntityState.Modified ))
        {
            foreach (var prop in entry.Entity.GetType().GetProperties().Where(p => p.GetCustomAttributes(typeof(AlwaysUpdateAttribute), true).Count() > 0).Select( p => p.Name ))
            {
                if (entry.State == System.Data.EntityState.Added || entry.State == System.Data.EntityState.Unchanged) continue;
                // Try catch removes the errors for detached and unchanged items
                try
                {
                    entry.Property(prop).IsModified = true;
                }
                catch { }
            }
        }
    }
    return base.SaveChanges();
}
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$
  • Instead of checking .Count() > 0 which needs to iterate over the IEnumerable you can just use .Any() which only checks if at least one item is contained in the IEnumerable

  • you should extract the result of typeof(AlwaysUpdateAttribute) to a variable.

    Type desiredType = typeof(AlwaysUpdateAttribute);
    
  • you can restrict the outer loop by adding the "continue condition" to the Where() method. For readability we will do this outside of the loop

    changeSet = changeSet.Where( c=>   
                c.State == System.Data.EntityState.Modified 
                  && !(entry.State == System.Data.EntityState.Added   
                  || entry.State == System.Data.EntityState.Unchanged)  
                 );  
    
  • you shouldn't shorten any variable names -> prop should be propertyName

Refactoring

Implementing all above will lead to

public override int SaveChanges()
{
    var changeSet = ChangeTracker.Entries();
    if (changeSet != null)
    {
        changeSet = changeSet.Where( c=>   
                 c.State == System.Data.EntityState.Modified 
                  && !(entry.State == System.Data.EntityState.Added   
                  || entry.State == System.Data.EntityState.Unchanged)  
                  );   

        Type desiredType = typeof(AlwaysUpdateAttribute);

        foreach (var entry in changeSet)
        {
            foreach (var propertyName in entry.Entity.GetType().GetProperties().Where(p => p.GetCustomAttributes(desiredType , true).Any()).Select( p => p.Name ))
            {
                // Try catch removes the errors for detached and unchanged items
                try
                {
                    entry.Property(propertyName).IsModified = true;
                }
                catch { }
            }
        }
    }
    return base.SaveChanges();
}


    foreach (var entry in changeSet) 
    {
        foreach (var prop in entry.Entity.GetType().GetProperties().Where(p => p.GetCustomAttributes(desiredType , true).Any()).Select( p => p.Name ))
        {
            // Try catch removes the errors for detached and unchanged items
            try
            {
                entry.Property(prop).IsModified = true;
            }
            catch { }
        }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.