10

Following Julia Lermas book 'DbContext' on a N-Tier solution of keeping track of changes, I provided each entity with a State property and a OriginalValues dictionary (through IObjectWithState). After the entity is constructed I copy the original values to this dictionary. See this sample (4-23) of the book:

public BreakAwayContext()
{
  ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += (sender, args) =>
  {
      var entity = args.Entity as IObjectWithState;
      if (entity != null)
      {
        entity.State = State.Unchanged;
        entity.OriginalValues = BuildOriginalValues(this.Entry(entity).OriginalValues);
      }
    };
}

In the constructor of the BreakAwayContext (inherited from DbContext) the ObjectMaterialized event is caught. To retrieve the original values of the entity, the DbEntityEntry is retrieved from the context by the call to this.Entry(entity). This call is slowing the process down. 80% of the time of this event handler is spend on this call.

Is there a faster way to retrieve the original values or the entities DbEntityEntry?

pexxxy
  • 489
  • 1
  • 6
  • 17
  • Have you tried her other suggestion, to store the list of changed values instead? I thought storing the original values would be expensive, so in my multi-tier (multi-platform) solution, I store a comma separated list containing changed properties (in Delphi by overriding the setters of each property in Delphi using T4 templates in .Net at first). In the DAL when an entity (or DTO) is sent for updates, I loop through and mark each changed property as modified. This doesn't explain a faster way to retrieve original values, but it will achieve disconnected change tracking. – reckface Oct 04 '12 at 11:49

1 Answers1

18

Context.Entry() calls DetectChanges() that depends on number of objects in context and could be very slow. In your case you could replace with faster version ((IObjectContextAdapter) ctx).ObjectContext.ObjectStateManager.GetObjectStateEntry(obj);

Ben
  • 2,454
  • 26
  • 32
  • Thank you! I just swapped out my code to use your alternate method. My get state calls when from 8 seconds to .003 – BigJoe714 Feb 24 '15 at 16:15
  • Amazing! get state calls from 4 seconds to practically 0! I used ((IObjectContextAdapter) ctx).ObjectContext.ObjectStateManager.GetObjectStateEntry(obj).ChangeState(EntityState.Modified); – Red Nightingale Aug 31 '16 at 02:13