Notifications for tracked changes in EntityFrameworks DbContext

.net c# entity-framework entity-framework-6 winforms

Question

I am building a Data Entry app using Entity Framework where a user can fill out forms and then Save or Cancel. However I want the Save Button only to be enabled when there is actual data that can be saved to the database.

I know about DbContext.ChangeTracker. However I was not able to find a possibility to get a notification form the context whenever there are changes.

Of couse I could track that manually, but that is tedious and error prone.

Update The App is a WinForms Application

Question: How can I get a notification from the DbContext when it "Is Dirty/Has changes"?

Update 2

Maybe this can clarify my Question:

This is what I don't want:

using(var ctx = new DbContext()) {
  var foo = new FooEntity();
  ctx.Add(foo);
  RaiseContextIsDirty();  //<-- don't want to do this, this should be automatic
  //.....
  ctx.SaveChanges();
  RaiseContextIsClean();  //<-- don't want to do this, this should be automatic
}

What I am looking for is something like this:

using(var ctx = new DbContext()) {
  ctx.ChangeTracker.OnDirtyChanged += ContextDirtyChanged;
  var foo = new FooEntity();
  ctx.Add(foo);   //<- fires OnDirtyChanged
  //.....
  ctx.SaveChanges();   //<- fires OnDirtyChanged
}
1
0
12/11/2015 10:47:55 PM

Popular Answer

So you could have this overridden implementation of the SaveChanges:

public class MyDbContext : DbContext
{
   public delegate void ChangeEventHandler(object sender, ChangeEventArgs e);
   public event ChangeEventHandler ChangeEvent;

   public override int SaveChanges()
   {
       var result = base.SaveChanges();

       var entitiesAdded = this.ChangeTracker.Entries.Where(x => x.State == EntityState.Added);
       var entitiesRemoved = this.ChangeTracker.Entries.Where(x => x.State == EntityState.Deleted);
       var entitiesModified = this.ChangeTracker.Entries.Where(x => x.State == EntityState.Modified);

       ChangeEvent(this, new ChangeEventArgs(entitiesAdded, entitiesRemoved, entitiesModified));

       return result;
   }

}

Just create a ChangeEventArgs by creating a class that implements EventArgs.

Then you should just be able to bind to the event the normal way:

ctx.ChangeEvent += (s, e) => Console.WriteLine("Changes happened");

Edit

I have just pulled most of this from MSDN, I haven't got time to test it properly. But I don't see this solution being too far wrong.

Further Thoughts

The DbSet<T> backs onto a IDbSet<T> so there is no reason why you couldn't implement your own IDbSet<T> and when you implemented your own Add function wire the events in. This would follow the same pattern as above.

Then in your MyDbContext listen to all this events and consolidate them into 1 event or handle them as they come.

0
9/21/2015 10:26:08 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow