none
Best way (performance) to determine whether or not the DbContext is dirty RRS feed

  • Question

  • Hi,

    I am using Entity Framework 4.1, Database first and the DbContext API.
    In my WPF MVVM application I am binding directly to my Entity Framework entities. There are two entities: Course and Department having a one-to-many relationship (Course exposes a navigation property to a single Department).

    My editor form contains a DataGrid containing a list of courses and a Save button. This button has its Command property bound to an ICommand property in my ViewModel. The CanExecute() method returns true if the DbContext has changes:

    return dbContext.ChangeTracker.Entries().Any(
        e => e.State == EntityState.Added || e.State == EntityState.Modified || e.State == EntityState.Deleted);
    

    Due to the inner workings of the WPF’s CommandManager this code is executed very often. This results in bad performance while browsing (using the Up and Down keys) through a DataGrid containing only 3 courses and 2 columns. One column of the DataGrid contains a AutoCompleteBox to select the related department. In my case there are 3000 departments.

    Is there another way to know if the DbContext has changes? Maybe it is possible to know that the context didn't changed since the last time we checked it for changes.

    Thanks,

    Michel Miranda

    Tuesday, June 28, 2011 12:13 PM

Answers

  • Hello Michel,

    AFAIK, I didn't find any methods or events can monitor if the DbContext was changed or not. I think you want to recieve the notification about entity objects. I suggest you can check ObjectStateMnager.ObjectStateManagerChanged Event which occurs when entities are added to or removed from the state manager. Please check here for more information. http://msdn.microsoft.com/en-us/library/system.data.objects.objectstatemanager.objectstatemanagerchanged.aspx

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, June 30, 2011 8:05 AM
  • Hello Larcolais,

    I followed your advise. Please take a quick look at it before I close this thread. Thank you.

    Here is my implementation of my custom DbContext:

    public partial class Entities
    {
      private bool isDirty;
    
      public bool IsDirty
      {
        get { return this.isDirty; }
      }
    
      public static Entities CreateDbContext()
      {
        Entities dbContext = new Entities();
        dbContext.Init();
    
        return dbContext;
      }
    
      private void Init()
      {
        this.Configuration.LazyLoadingEnabled = false;
    
        this.isDirty = false;
    
        ObjectStateManager objectStateManager = (this as IObjectContextAdapter).ObjectContext.ObjectStateManager;
        objectStateManager.ObjectStateManagerChanged += new CollectionChangeEventHandler(OnObjectStateManagerChanged);
      }
    
      private void OnObjectStateManagerChanged(object sender, CollectionChangeEventArgs e)
      {
        EntityBase entity = e.Element as EntityBase;
        if (entity == null) return;
    
        switch (e.Action)
        {
          case CollectionChangeAction.Add:
            ObjectStateManager objectStateManager = (this as IObjectContextAdapter).ObjectContext.ObjectStateManager;
    
            EntityState entityState = objectStateManager.GetObjectStateEntry(entity).State;
    
            if (entityState == EntityState.Added || entityState == EntityState.Modified)
            {
              this.isDirty = true;
            }
    
            entity.EntityChanged += new EventHandler(OnEntityChanged);
            break;
          case CollectionChangeAction.Remove:
            this.isDirty = true;
    
            entity.EntityChanged -= new EventHandler(OnEntityChanged);
            break;
        }
      }
    
      private void OnEntityChanged(object sender, EventArgs e)
      {
        this.isDirty = true;
      }
    }
    

    All my entities inherit EntityBase that fires an event when the entity changes.

    Thanks,

    Michel Miranda

    Friday, July 1, 2011 1:08 PM

All replies

  • Hello,

    Thank you for posting.

    From your description, you added Command to your Button. ChangeTracker looks good.  You might consider use this rather than Local as ObservableCollection didn’t have great performance. I suspect that your question is focused on how you defined the Command. Could you please provide more detailed information for code snippet of Command.

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, June 29, 2011 7:00 AM
  • Hi Larcelois,

    Thanks for your reponse.

    I will try to be more clear. The point is that I need a method indicating whether the DbContext is dirty or not. Here is the definition:

    public bool HasChanges
    {
      get
      {
        return dbContext.ChangeTracker.Entries().Any(
          e => e.State == EntityState.Added || e.State == EntityState.Modified || e.State == EntityState.Deleted);
      }
    }
    

    This method is being called very frequently (every time something changes in the UI). When the DbContext contains a lot of entities, the performance of my UI is bad. So in my case I need a smarter way for checking the state of the ChangeTracker.

    My question is:

    Is there another way to know if the DbContext has changes? Why doesn't the DbContext API exposes a HasChanges property? 

    Maybe it is possible to know that the context didn't changed since the last time I checked it for changes, so I can cache the boolean value.

    Thanks,

    Michel

    Wednesday, June 29, 2011 8:29 AM
  • Hello Michel,

    AFAIK, I didn't find any methods or events can monitor if the DbContext was changed or not. I think you want to recieve the notification about entity objects. I suggest you can check ObjectStateMnager.ObjectStateManagerChanged Event which occurs when entities are added to or removed from the state manager. Please check here for more information. http://msdn.microsoft.com/en-us/library/system.data.objects.objectstatemanager.objectstatemanagerchanged.aspx

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Thursday, June 30, 2011 8:05 AM
  • Hello Larcolais,

    I followed your advise. Please take a quick look at it before I close this thread. Thank you.

    Here is my implementation of my custom DbContext:

    public partial class Entities
    {
      private bool isDirty;
    
      public bool IsDirty
      {
        get { return this.isDirty; }
      }
    
      public static Entities CreateDbContext()
      {
        Entities dbContext = new Entities();
        dbContext.Init();
    
        return dbContext;
      }
    
      private void Init()
      {
        this.Configuration.LazyLoadingEnabled = false;
    
        this.isDirty = false;
    
        ObjectStateManager objectStateManager = (this as IObjectContextAdapter).ObjectContext.ObjectStateManager;
        objectStateManager.ObjectStateManagerChanged += new CollectionChangeEventHandler(OnObjectStateManagerChanged);
      }
    
      private void OnObjectStateManagerChanged(object sender, CollectionChangeEventArgs e)
      {
        EntityBase entity = e.Element as EntityBase;
        if (entity == null) return;
    
        switch (e.Action)
        {
          case CollectionChangeAction.Add:
            ObjectStateManager objectStateManager = (this as IObjectContextAdapter).ObjectContext.ObjectStateManager;
    
            EntityState entityState = objectStateManager.GetObjectStateEntry(entity).State;
    
            if (entityState == EntityState.Added || entityState == EntityState.Modified)
            {
              this.isDirty = true;
            }
    
            entity.EntityChanged += new EventHandler(OnEntityChanged);
            break;
          case CollectionChangeAction.Remove:
            this.isDirty = true;
    
            entity.EntityChanged -= new EventHandler(OnEntityChanged);
            break;
        }
      }
    
      private void OnEntityChanged(object sender, EventArgs e)
      {
        this.isDirty = true;
      }
    }
    

    All my entities inherit EntityBase that fires an event when the entity changes.

    Thanks,

    Michel Miranda

    Friday, July 1, 2011 1:08 PM
  • Cheers! I'm glad I can help. If you have any question later, welcome to post back.

    Best Regards,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Saturday, July 2, 2011 1:48 PM
  • I've noticed this a lot of times and always wondered why in MSDN forums all questions and answers appear twice? It makes it very hard to read, thanks for answer. Michal
    Monday, April 21, 2014 11:29 PM