Transaction scope and web apis
-
One of my API controllers is hitting two databases each on its own context, and I do not want any tables updated until I am satisfied that it is safe. With that in mind I wrapped the code in a C# transaction scope but when I reached a point where I had to fire scope.dispose, the API call crashed out with a code 500 and any previously executed inserts were not rolled back. I have successfully applied entity framework core transaction protection to the code block so it is not an issue, but I am curious to know if anyone has tried and succeeded or failed in the same thing. A quick look online did not show up anything.
Ger
-
One of my API controllers is hitting two databases each on its own context, and I do not want any tables updated until I am satisfied that it is safe. With that in mind I wrapped the code in a C# transaction scope but when I reached a point where I had to fire scope.dispose, the API call crashed out with a code 500 and any previously executed inserts were not rolled back. I have successfully applied entity framework core transaction protection to the code block so it is not an issue, but I am curious to know if anyone has tried and succeeded or failed in the same thing. A quick look online did not show up anything.
Ger
Ger Hayden wrote:
when I reached a point where I had to fire scope.dispose, the API call crashed out with a code 500 and any previously executed inserts were not rolled back.
Dispose throws away the object. If you want to do a rollback, you call DbTransaction.Rollback Method (System.Data.Common) | Microsoft Docs[^], instead of commit.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
Ger Hayden wrote:
when I reached a point where I had to fire scope.dispose, the API call crashed out with a code 500 and any previously executed inserts were not rolled back.
Dispose throws away the object. If you want to do a rollback, you call DbTransaction.Rollback Method (System.Data.Common) | Microsoft Docs[^], instead of commit.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
That pretty much sums it up. Somehow I got it into my head that if I did not have a scope.complete, then I had to have a scope.dispose to ensure that everything got cleaned up. If I had left it out I would probably have achieved the effect I wanted. All About Transaction Scope here on CP has both a .Rollback and a .Dispose as capable of rollback in section 20. If I had read this instead of one of the shorter articles I would have seen that I had a choice. Equally it looks like I would have got an automatic dispose (and rollback) just by throwing an exception as needed. Good to know.
Ger
-
Ger Hayden wrote:
when I reached a point where I had to fire scope.dispose, the API call crashed out with a code 500 and any previously executed inserts were not rolled back.
Dispose throws away the object. If you want to do a rollback, you call DbTransaction.Rollback Method (System.Data.Common) | Microsoft Docs[^], instead of commit.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
TransactionScope[^] doesn't have a
Rollback
method.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
TransactionScope[^] doesn't have a
Rollback
method.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
True. TransactionScope makes it possible for plain C# code to be transactional, where DBTransaction is as it says. The factory-method on IDbConnection will return a IDbTransaction, not a TransactionScope.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
-
True. TransactionScope makes it possible for plain C# code to be transactional, where DBTransaction is as it says. The factory-method on IDbConnection will return a IDbTransaction, not a TransactionScope.
Bastard Programmer from Hell :suss: If you can't read my code, try converting it here[^] "If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
But Ger's using
TransactionScope
and Entity Framework. :)
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
But Ger's using
TransactionScope
and Entity Framework. :)
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
One of my API controllers is hitting two databases each on its own context, and I do not want any tables updated until I am satisfied that it is safe. With that in mind I wrapped the code in a C# transaction scope but when I reached a point where I had to fire scope.dispose, the API call crashed out with a code 500 and any previously executed inserts were not rolled back. I have successfully applied entity framework core transaction protection to the code block so it is not an issue, but I am curious to know if anyone has tried and succeeded or failed in the same thing. A quick look online did not show up anything.
Ger
I think it's a limitation of EF Core:
Transactions - EF Core | Microsoft Docs[^]:
As of version 2.1, the System.Transactions implementation in .NET Core does not include support for distributed transactions, therefore you cannot use TransactionScope or CommittableTransaction to coordinate transactions across multiple resource managers.
It's not clear whether that limitation also applies to EF Core on .NET Framework, but I suspect it would.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
I think it's a limitation of EF Core:
Transactions - EF Core | Microsoft Docs[^]:
As of version 2.1, the System.Transactions implementation in .NET Core does not include support for distributed transactions, therefore you cannot use TransactionScope or CommittableTransaction to coordinate transactions across multiple resource managers.
It's not clear whether that limitation also applies to EF Core on .NET Framework, but I suspect it would.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
EF Core's own transaction handling looks like it is doing the job in early testing.
Ger
-
TransactionScope[^] doesn't have a
Rollback
method.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
This is the rollback I was referring to (from the CP article):
using (var scope = new TransactionScope())
{
//either 1 of following lines will use
Transaction.Current.Rollback();
scope.Dispose();
//if you comment the following line transaction will
//automatically be rolled back
//scope.Complete();
}Ger