When you create a new TransactionScope, you might be surprised to find that the default isolation level is Serializable.
TransactionScope’s default constructor defaults the isolation level to Serializable and the timeout to 1 minute. In SQL Server, SERIALIZABLE transactions are rarely useful and prone to deadlocks.
If you are using a TransactionScope and getting deadlocks in your application (and hopefully you have a retry mechanism for SQLException 1205), it might be due to the Serializable isolation level.
Instead of using the default constructor:
using (var scope = new TransactionScope()) { // .... Do Stuff .... scope.Complete(); }
Use this:
using (var scope = TransactionUtils.CreateTransactionScope()) { // .... Do Stuff .... scope.Complete(); } ..... public class TransactionUtils { public static TransactionScope CreateTransactionScope() { var transactionOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted, Timeout = TransactionManager.MaximumTimeout }; return new TransactionScope(TransactionScopeOption.Required, transactionOptions); } }
[The other gotcha relates to SQL Server 2014 and below: TransactionScope and Connection Pooling]