e.g. When deadlock occurs, following SQL commands are successfully executed, even if they have assigned SQL transaction that is after rollback. It seems, it is caused by a new implicit transaction that is created on SQL Server.
Someone could expect that ADO.NET would throw an exception that the commands are being executed on a zombie transaction. However, such exception is not thrown. (I think this is a bug in ASP.NET.) Moreover, because of zombie transaction the final Dispose()
silently ignores the rollback.
Any ideas, how can I ensure that nobody can execute commands on implicit transaction?
Or, how to check that transaction is zombie? I found that Commit()
and Rollback()
check for zombie transaction, however I can call them for a test:)
I also found that also reading IsolationLevel will do the check, but I am not sure whether simple calling transaction.IsolationLevel.ToString();
will not be removed by a future optimizer. Or do you know any other safe way invoke a getter (without using reflection or IL emitting)?
EDIT: Remus Rusanu pointed out that this situation would not normally occur. Yes, that's true. It usually occurs when there is a bug in a code. In our case, there was some logging routine in a finally statement that was trying to store the failure into the database. Now, I am trying to find a solution how to detect such bugs in a future. Since these bugs are difficult to test. If ADO.NET would check that the provided transaction is zombie, this bug will be found much more easily. I found two possibilities:
- Turn off creation of implicit transactions - I am not sure whether this is possible.
- Ensure that before executing any commands, check for zombie transaction will run.