Entity Framework – Discarding changes

While this may seem old to some, it’s going to be new to others I hope. I’m in the midst of writing an internal application in WPF using Entity Framework (Code First) for the data both of which are reasonably ‘new’ to me. As in I’ve played with them but yet to really work with them full scale. This may seem strange to some but my company is slow to change and introduction of new technology is a slow and painful process. One issue I encountered is being able to discard any changes made to an entity. Let me explain.

I have a grid displaying a list of data. An edit button takes the user to a popup edit form. As the entity is passed from the grid and everything is bound together, any changes in the edit form are reflected in the grid. So hitting Save at this point is really just to update the contents of the database. The problem occurs when the user decides to discard the changes. Hit cancel closes the form but does not revert the changes to the underlying data entity. So what we have now is a grid showing data that does not match the database. Not very good at all.

I started to research ways to revert the entity back to it’s original value and found that I could use the Reload method. So I came up with this piece of code to reattach my entity to my data context and reload the values.

// Find the 'entry' and reload it
var entityEntry = dataContext.Entry(dataEntity);
entityEntry .Reload();

So while this may or may not be the most efficient it works. Or at least I thought it did until I started moving to more complex edit forms with contained grids for ‘child’ data.

For this child data I’m using the same pattern. Editing is via a popup edit form. The reload did not refresh any of the child data. So a bit of searching resulted in the following code

var refreshableObjects =
  dataContext.ObjectContext.ObjectStateManager.GetObjectStateEntries(
    EntityState.Added | EntityState.Deleted | EntityState.Modified |  EntityState.Unchanged)
  .Where(i => i.EntityKey != null).Select(i => i.Entity);

  dataContext.ObjectContext.Refresh(RefreshMode.StoreWins, refreshableObjects);

Note that I have an property coded to get the ObjectContext from the dataContext

public ObjectContext ObjectContext
{
  get { return ((IObjectContextAdapter) this).ObjectContext; }
}

So I tried this and it worked, all new entities where removed, all update entities where reverted and all deleted entities where NOT restored. Yep, I still had an issue. My delete code was simple, I use a button in the grid to delete the row, nothing fancy.

// Get the data context of the grid row
var item = (DataType) ((Button) sender).DataContext;</code>

// Remove from the child collection
dataContext.childItems.Remove(item);

Seems simple enough and it works. Searching around I couldn’t figure out why this code caused in issue in EF. After a bit of head scratching I realized that my refresh code was looking for entities in the data context in the Deleted state, whereas I was actually deleting the entity, not setting it’s state. So I changing the delete code to

// Get the data context of the grid row
var item = (DataType) ((Button) sender).DataContext;

// 'Delete it' in the data contexts
dbContext.Entry(item).State = EntityState.Deleted;

// Rebind grid
childGridView.Rebind();

This was the correct change. I’m now marking the entity as deleted, so that my refresh code can find it and the grid rebind, refreshes my grid which correctly does not show the deleted item.

So is the best solution to the issue, I can’t say that I know that as there seem to be many ways to try and refresh data in EF, but this way works and I’m happy with that.

Advertisements

About Colin Blakey

Way to many years (25+) working in the Financial software world.
This entry was posted in Entity Framework. Bookmark the permalink.

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