(SQL SERVER 2008) If a Transaction Timeout error occurs within a TransactionScope (.Complete()) would you expect the transaction to be rolled back?
Update:
The error is actually being thrown in the closing curly brace (i.e. .Dispose()), not .Complete(). Full error is:
The transaction has aborted. System.Transactions.TransactionAbortedException TransactionAbortedException System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.TimeoutException: Transaction Timeout
--- End of inner exception stack trace ---
at System.Transactions.TransactionStateAborted.BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState)
at System.Transactions.CommittableTransaction.Commit()
at System.Transactions.TransactionScope.InternalDispose()
at System.Transactions.TransactionScope.Dispose()
As far as I can tell the transaction is not rolled back and the tables remained locked until I issued a KILL against the SPID/session_id.
I used DBCC OPENTRAN to get the oldest transaction and then KILL it. I have tried KILL WITH STATUS but get a message that no status is available as nothing is being rolled back. Status of the SPID/session_id in sys.dm_exec_sessions is 'sleeping'. Code snippet:
try
{
using (var transaction = new TransactionScope())
{
LOTS OF WORK CARRIED OUT WITH LINQ ENTITIES/SubmitChanges() etc.
transaction.Complete(); //Transaction timeout
}
return result;
}
catch (Exception ex)
{
logger.ErrorException(ex.Message, ex);
result.Fail(ex.Message);
return result;
}
UPDATE:
Problem is not entirely solved, but further information should anyone else have this problem.
I feel a rebuild of the database and a rethink of some business functionality coming on...
I'm thinking that the TransactionAbortedException is actually a timeout. If so you should find that the InnerException of the TransactionAbortedException is a timeout.
You should be able to get rid of it by making sure that the timeout of the transactionscope is longer than the command timeout.
Try changing the transaction scope to something like this:
new TransactionScope(TransactionScopeOption.Required, TimeSpan.FromSeconds(60))
And also set an explicit timeout on your context. Should be something like:
myContext.CommandTimeout = 30; //This is seconds