I am building an API where I get a specific object sent as a JSON and then it gets converted into another object of another type, so we have sentObject
and convertedObject
. Now I can do this:
using (var dbContext = _dbContextFactory.CreateDbContext())
using (var dbContext2 = _dbContextFactory2.CreateDbContext())
{
await dbContext.AddAsync(sentObject);
await dbContext.SaveChangesAsync();
await dbContext2.AddAsync(convertedObject);
await dbContext2.SaveChangesAsync();
}
Now I had a problem where the first SaveChanges
call went ok but the second threw an error with a datefield that was not properly set. The first SaveChanges
call happened so the data is inserted in the database while the second SaveChanges
failed, which cannot happen in my use-case.
What I want to do is if the second SaveChanges
call goes wrong then I basically want to rollback the changes that have been made by the first SaveChanges
.
My first thought was to delete cascade
but the sentObject
has a complex structure and I don't want to run into circular problems with delete cascade
.
Is there any tips on how I could somehow rollback my changes if one of the SaveChanges
calls fails?
You can call context.Database.BeginTransaction
as follows:
using (var dbContextTransaction = context.Database.BeginTransaction())
{
context.Database.ExecuteSqlCommand(
@"UPDATE Blogs SET Rating = 5" +
" WHERE Name LIKE '%Entity Framework%'"
);
var query = context.Posts.Where(p => p.Blog.Rating >= 5);
foreach (var post in query)
{
post.Title += "[Cool Blog]";
}
context.SaveChanges();
dbContextTransaction.Commit();
}
(taken from the docs)
You can therefore begin a transaction for dbContext
in your case and if the second command failed, call dbContextTransaction.Rollback();
Alternatively, you can implement the cleanup logic yourself, but it would be messy to maintain that as your code here evolves in the future.