Retrieving Changed Properties from the Entity Framework

On a project using the Entity Framework (3.5 SP1), I was tasked with only sending “changed” or “added” values to a back-end system to keep network traffic down.  After a lot of research and testing, I came up with the solution below.

Use this code below:

private static void FindChangedEntityProperties<T>(LocalEntityState state,
                                                     ClientDataEntities context,
                                                     ref IEnumerable<string> props,
                                                     ref ObjectStateEntry ose)
  {
    if (state == LocalEntityState.Modified)
    {
      ose = context.ObjectStateManager.GetObjectStateEntries<T>(
                                                            EntityState.Modified)
                                                            .FirstOrDefault();
      if (ose != null)
      {
        props = ose.GetModifiedProperties();
      }
    }
    else
    {
      ose = context.ObjectStateManager.GetObjectStateEntries<T>(EntityState.Added |
                                                            EntityState.Modified
                                                            ).FirstOrDefault();
      if (ose == null)
      {
        return;
      }
      else
      {
        var stateEntry = context.ObjectStateManager.GetObjectStateEntry(ose.Entity);
        props = (from
                   fm in stateEntry.CurrentValues.DataRecordInfo.FieldMetadata
                 where
                   stateEntry.CurrentValues.IsDBNull(fm.Ordinal) == false
                 select
                   fm.FieldType.Name
                ).ToArray();
      }
    }
    //Sort (helps with switch statements)
    if (props != null && props.Count() > 0)
    {
      props = props.OrderBy(p => p.ToUpper());
    }
  }

Add this extension method:

public static IEnumerable<ObjectStateEntry> GetObjectStateEntries<TEntity>(this
                                                            ObjectStateManager osm,
                                                            EntityState state)
{
  return from 
           entry in osm.GetObjectStateEntries(state)
         where 
           entry.Entity is TEntity
         select 
           entry;
}

Usage:

IEnumerable<string> pp = null;
ObjectStateEntry pState = null;

FindEntityPropertiesToReport<Person>(p.EntityState, context, ref jp, ref pState);

if (pp != null && pp.Count() > 0)
{
  foreach (var propName in pp)
  {
    //Example of pulling out a DateTime property
    var changedProp = pState.CurrentValues.GetDateTime(pState.CurrentValues
                                                            .GetOrdinal(propName));
  }
}

Tip By: David McCarter

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s