Reputation: 135
When trying to debug something I found code that was effectively doing the following:
Now - Creating a transaction and not committing is probably a bad idea anyway - especially when having (and that was the bug fix).
However when testing this - I tried various combinations of the above (committing all transactions, some transactions, no transactions (i.e. only TScope) committing the First, but not second, adding other transactions etc) and in all thesting I found that the following to be true:
Only when I failed to commit the first transaction AND the transaction scope became distributed, the Dispose of the TScope would fail with:
System.InvalidOperationException : The operation is not valid for the current state of the enlistment.
I am now curious and would like to know why this is the case?
Upvotes: 1
Views: 2459
Reputation: 5629
I suspect the problem you see is covered by one of these: https://nhibernate.jira.com/issues/?jql=project%20%3D%2010000%20AND%20labels%20%3D%20TransactionScope
I'm not entirely sure what happens but I've seen similar behaviour, e.g. if NH enlists in the ambient transaction, and the transaction later becomes distributed, calling TransactionScope.Complete() might hang for 20 seconds and then fail.
NH will try to enlist in a TransactionScope even if you don't use an NH transaction. In this case, NH will flush changes during the ambient transaction's Prepare() phase. It will do this on the db connection, but that has also enlisted in the transaction and will get its own Prepare() call. Unfortunately I haven't been able to figure out the exact problem, but I suspect what happens is that in some circumstances the db connections Prepare() will be called before NHibernate's Prepare(). The latter will try to continue to use the db connection, and it appears this causes some sort of deadlock.
Using a NH transaction and committing this before completing the transaction scope will make NH flush its changes before the underlying DB connection enters the prepare-phase.
Upvotes: 1