The standard way to manage exceptions in ASP.NET (and by extension, MVC) web applications is to use the System.Transactions.TransactionScope class. It contains some useful properties:
- Auto Transaction Start: As soon as you instantiate the
TransactionScopeinstance, it starts the transaction. - Database Level: By default, this affects all connections in and out of the database. This means you can use it even when you don’t have access to the connection instance.
- Disposable: TransactionScope implements
IDisposable, meaning if you wrap it in ausingstatement, it automatically commits the transaction (or rolls back if an exception occurs).
But the question is, how do you manually force a transaction to roll back? For example, in your integration/functional tests, you may want to start a transaction in the setup method, and roll it back in the tear-down method.
Oddly, there is no Rollback method (although there is a Complete method to force commiting the transaction). The answer, oddly enough, is to manually invoke Dispose.
I confirmed by decompiling the .NET 4.5 source that calling Dispose rolls back the transaction.
In my situation, this came with quite a cost: in a simple functional test, the runtime tripled (from 15s with manual clean-up, to 45s with a transaction). So be weary, and make sure you pick the solution that works for you.