A general pattern for me in a project using Entity Framework 6 is to
DBSet
of the DbContext
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.
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.