Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DbContext and RejectChanges

I was working with RIA services where ObjectContext has RejectChanges() method. However, I am now working with EF 4.4 in a desktop application and I cannot find that method. So, my question is: in a scenrario where I allow user to do batch CrUD operations on collection, how would I revert all the changes? I could go with recreating the Context and fetching the data again, but that sound highly unnecessary if I need to revert changes back to 1-2 entities.

So, what is the best way to reject changes? And also, how do we know if the context is doing something (IsBusy)?

like image 526
Goran Avatar asked May 10 '12 13:05

Goran


People also ask

What is meant by DbContext and DbSet?

DbContext generally represents a database connection and a set of tables. DbSet is used to represent a table. Your code sample doesn't fit the expected pattern.

What is the purpose of DbContext?

A DbContext instance represents a combination of the Unit Of Work and Repository patterns such that it can be used to query from a database and group together changes that will then be written back to the store as a unit. DbContext is conceptually similar to ObjectContext.

Is DbContext part of Entity Framework?

The DbContext class is an integral part of Entity Framework. An instance of DbContext represents a session with the database which can be used to query and save instances of your entities to a database. DbContext is a combination of the Unit Of Work and Repository patterns.

Is DbSet part of DbContext?

The DbSet class represents an entity set that can be used for create, read, update, and delete operations. The context class (derived from DbContext ) must include the DbSet type properties for the entities which map to database tables and views.


2 Answers

EF doesn't have any direct "reject changes" operation. You can go through entity entries in ChangeTracker / ObjectStateManager and overwrite current values with original values for modified entities. You can also detach added entities and change deleted entities back to unchanged but that all will mostly work only if you (or EF internally) didn't change the state of any independent association (relation). If you work with relations as well the whole thing can become much more complicated because you must revert relations as well - in such case it is simpler to reload data.

For reverting changes in DbContext API you can try this:

foreach (var entry in context.ChangeTracker
                             .Entries<YourEntityType>()
                             .Where(e => e.State == EntityState.Modified))
{
    entry.CurrentValues.SetValues(entry.OriginalValues);
}

In this case I think the main problem is the way how you work with entities - you allow changes on live data and EF does its logic on behind to keep data consistent when changes are performed but later on you decide that those changes will not be saved. In this case you should do one of following:

  • Discard changed data and reload whole data set (by recreating the context)
  • Separate this logic to not work on live data and push data modification to EF context only when the modification is really confirmed

Context is doing something if you say it to do something. It never becomes busy itself.

like image 109
Ladislav Mrnka Avatar answered Oct 12 '22 17:10

Ladislav Mrnka


public void RejectChanges()
        {
            foreach (var entry in ChangeTracker.Entries())
            {
                switch (entry.State)
                {
                    case EntityState.Modified:
                        {
                            entry.CurrentValues.SetValues(entry.OriginalValues);
                            entry.State = EntityState.Unchanged;
                            break;
                        }
                    case EntityState.Deleted:
                        {
                            entry.State = EntityState.Unchanged;
                            break;
                        }
                    case EntityState.Added:
                        {
                            entry.State = EntityState.Detached;
                            break;
                        }
                }
            }
        }
like image 11
Sergey Shuvalov Avatar answered Oct 12 '22 18:10

Sergey Shuvalov