In my C# code I am using TransactionScope because I was told not to rely that my sql programmers will always use transactions and we are responsible and yada yada.
Having said that
It looks like TransactionScope object Rolls back before the SqlTransaction? Is that possible and if so what is the correct methodology for wrapping a TransactionScope in a transaction.
Here is the sql test
CREATE PROC ThrowError
AS
BEGIN TRANSACTION --SqlTransaction
SELECT 1/0
IF @@ERROR<> 0
BEGIN
ROLLBACK TRANSACTION --SqlTransaction
RETURN -1
END
ELSE
BEGIN
COMMIT TRANSACTION --SqlTransaction
RETURN 0
END
go
DECLARE @RESULT INT
EXEC @RESULT = ThrowError
SELECT @RESULT
And if I run this I get just the divide by 0 and return -1
Call from the C# code I get an extra error message
Divide by zero error encountered.
Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION tatement is missing. Previous count = 1, current count = 0.
If I give the sql transaction a name then
Cannot roll back SqlTransaction.
No transaction or savepoint of that name was found.
Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK
TRANSACTION statement is missing. Previous count = 1, current count = 2.
some times it seems the count goes up, until the app completely exits
The c# is just
using (TransactionScope scope = new TransactionScope())
{
... Execute Sql
scope.Commit()
}
EDIT:
The sql code has to work for 2000 and 2005
There was a massive upgrade to the error handling within SQL Server 2005. These articles are fairly extensive: Error Handling in SQL 2005 and Later by Erland Sommarskog and Error Handling in SQL 2000 – a Background by Erland Sommarskog
The best way is something like this:
Create your stored procedure like:
however that is only for SQL Server 2005 and up. Without using the TRY-CATCH blocks in SQL Server 2005, you have a very difficult time removing all of the messages that SQL Server sends back. The
extra messagesyou refer to are caused by the nature of how rollbacks are handled using @@trancount:from http://www.sommarskog.se/error-handling-I.html#trancount
If you don’t want to get the warning about the transaction count not matching, you need to only have one transaction open at any one time. You do this by creating all of your procedure like this:
By doing this, you only issue the transaction commands if you are not already in a transaction. If you code all of your procedures this way, only the procedure or the C# code that issues the BEGIN TRANSACTION will actually issue the COMMIT/ROLLBACK and the transaction counts will always match (you won’t get an error).
in C# from TransactionScope Class Documentation:
Just a thought, but you might be able to use the
TransactionAbortedExceptioncatch to get the actual error and ignore the transaction count mismatch warning.