Rollback additions / removals to DBSets of the DbContext using a transaction in Entity Framework

c# dbcontext entity-framework entity-framework-6

Question

A general pattern for me in a project using Entity Framework 6 is to

  1. Create new entities for addition
  2. Add the entities to the relevant DBSet of the DbContext
  3. Set the properties of these objects
  4. Call DbContext.SaveChanges()

Here is some pseudo-code for what I mean:

    // Psuedo code to illustrate process. 
    void AddProcess()
    {

        var modelsToAdd = GetModelsToAdd();

        try
        {
            _context.Models.AddRange(modelsToAdd);

            _context.SaveChanges();

            // If we get here all is good.
        }
        catch (Exception ex)
        {
            _context.RemoveRange(modelsToAdd);
            throw;
        }
        finally
        {
            //....
        }
    }

I am aware the SaveChanges() method internally creates its own Transaction, so that if there is an exception during the save this will be rolled back. However, what I want is for the added entities in (2) to be removed from the DbSet if an error occurs during SaveChanges(). Basically, as if the 'Add' process had never taken place.

As you can see, at the moment I am caching a list of the models involved, and then removing them if an exception happens.

What I would like to know is there a better way to do this with Transactions automatically doing the work for me? So, can the internal Transaction rollback of SaveChanges() also rollback any additions to the DbSet's? Or can other Transactions be used?

What is the best / preferred way to achieve what I am looking for? I'm fairly new to EF, so this might be something obvious.

1
1
9/17/2018 10:12:29 PM

Accepted Answer

Option #1 from https://code.msdn.microsoft.com/How-to-undo-the-changes-in-00aed3c4 is typically enough for most implementations where you want to roll-back changes in the DbContext without dropping and re-instantiating a Context. Generally the request would have failed and the call would have ended so the DbContext scope should end until a retry is attempted in a new request.

I'd only be looking at rolling back a DbContext if there was a really good reason for an immediate retry/alternate action. Wanting to roll back DbSets in the case of a SaveChanges failure is usually an indicator that a DbContext that is being kept alive too long.

Important things like logging that need to be saved in the case of a failure should use a dedicated DbContext so that their updates are not hindered by a failed SaveChanges on the application's DbContext.

0
9/12/2018 6:26:07 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