How Does Transactionscope Roll Back Transactions

How does TransactionScope roll back transactions?

Essentially TransactionScope doesn't track your Adapter's, what it does is it tracks database connections. When you open a DB connection the connections will looks if there is an ambient transaction (Transaction Scope) and if so enlist with it. Caution if there are more the one connection to the same SQL server this will escalate to a Distribtued Transaction.

What happens since you're using a using block you are ensuring dispose will be called even if an exception occurs. So if dispose is called before txScope.Complete() the TransactionScope will tell the connections to rollback their transactions (or the DTC).

Does C# TransactionScope rollback if an exception is thrown while committing?

Just found the answer: It will rollback and throw a TransactionException.

According to the Microsoft documentation, TransactionScope commits the transactions by calling the CommittableTransaction.Commit method.

https://docs.microsoft.com/en-us/dotnet/framework/data/transactions/implementing-an-implicit-transaction-using-transaction-scope

Let's see what the CommittableTransaction.Commit method do:

When this method is called, all objects that have registered to participate in the transaction are polled and can independently indicate their vote to either commit or roll back the transaction. If any participant votes to roll back the transaction, it is rolled back and this method throws a TransactionException exception. This is a normal occurrence for a transaction and your code should catch and process such exceptions.

Microsoft documentation on CommittableTransaction Class: https://docs.microsoft.com/en-us/dotnet/api/system.transactions.committabletransaction.commit?view=net-5.0#System_Transactions_CommittableTransaction_Commit

try
{
using (TransactionScope transactionScope = new TransactionScope())
{
WriteToCloudDatabase(input);
transactionScope.Complete();
}
}
catch (TransactionException)
{
// If something wrong happens while committing the transaction,
// it will rollback and throw this exception.
}
catch (Exception)
{
// If something wrong happens before committing the transaction,
// it will rollback and that exception will be caught in here.
}

Triggering a rollback inside transactionscope C#

It's not committed as long as you don't call the 'Complete'. Remove that and it will be rollbacked when you leave the using of the scope:

using(TransactionScope scope)
{
//Run the procedure and save the return value in a variable
int rowsAffected = MyStoredProcedure();

//Print the value in the variable
Console.WriteLine(rowsAffected);

//Don't call Complete() and it will be rollbacked
//scope.Complete();
}

What is the best way to rollback a .net transaction?

if you know you want to rollback then do that explicitly. You are not guaranteed that Dispose will rollback (in the case where complete has been called, the transaction will be committed when you call Dispose)

to your question about using or new/Dispose they are not equivalent

using(var ts = new TransactionScope())
{
}

is equivalent to

TransactionScope ts;
try
{
ts = new TransactionScope();
}
finally
{
ts.Dispose();
}

to answer your follow up question no if you call Dispose you will not have your transaction "hanging around" it will either commit or rollback. However if you use the new/dispose as you wrote it (no finally block) you can have a situation where dispose isn't called when you expect it to be (in the case of an exception)

Transactionscope rollback

If you do not use RequireNew in you inner method, the inner method will be automatically rolled back if the parent fails to commit the transaction.

What error are you getting?



Related Topics



Leave a reply



Submit