HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

AlwaysUpdate attribute for Entity Framework Code First POCO

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
alwaysupdatefirstforattributecodepocoframeworkentity

Problem

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

Solution

-
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 { }
        }

Code Snippets

Type desiredType = typeof(AlwaysUpdateAttribute);
changeSet = changeSet.Where( c=>   
            c.State == System.Data.EntityState.Modified 
              && !(entry.State == System.Data.EntityState.Added   
              || entry.State == System.Data.EntityState.Unchanged)  
             );
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 { }
        }

Context

StackExchange Code Review Q#20726, answer score: 3

Revisions (0)

No revisions yet.