Open inglun opened 3 years ago
Funny. I thought someone would react to this report. When using TransactionScope you would never expect a timed out transaction to be partially committed.
Maybe because it seems unlikely to contributors this has anything to do with NHibernate. If things actually land into DB although the scope is not committed, while used connections were enlisted in the transaction, that is a transaction scope bug.
@inglun Maybe you could elaborate a little bit. Are you suggesting that NHibernate somehow disposes the TransactionScope by mistake somewhere? Are you saying that changes made on the connection before such dispose are still persisted? Or that the connection lives on and becomes unenlisted when the transaction scope is somehow disposed to early and that something does more changes on the connection afterwards?
It used to be that an NHibernate session should always have an NHibernate transaction, even if there is an outer TransactionScope. It appears you don't. I haven't kept up to date with recent NH releases though - if this requirement has been relaxed or not.
So, are you causing a timeout during your call to session.Flush(), and you believe that error somehow makes NH either unenlist the connection from the TransactionScope, or that NH in some way keeps using the connection after the TransactionScope has been somehow destroyed and the connection unenlisted?
Maybe because it seems unlikely to contributors this has anything to do with NHibernate. If things actually lands into DB although the scope is not committed, while used connections were enlisted in the transaction, that is a transaction scope bug.
Yes. It is so very unlikely that I almost laughed at my coworker that first reported a behavior consistent with this
@inglun Maybe you could elaborate a little bit. Are you suggesting that NHibernate somehow disposes the TransactionScope by mistake somewhere? Are you saying that changes made on the connection before such dispose are still persisted? Or that the connection lives on and becomes unenlisted when the transaction scope is somehow disposed to early and that something does more changes on the connection afterwards?
I am saying (in the code) that it is "as if" the TransactionScope is disposed. Not that it is. Disposing the TransactionScope is the only way I could "reproduce" the behavior without NHibernate (with plain ADO.Net). The connection "lives on" and above all it is used. In my test case a bunch of inserts are issued on it after timeout and they are committed instantly since the default default behavior of/in SQL Server is AUTOCOMMIT. Disabling autocommit with SET IMPLICIT_TRANSACTIONS ON doesn't stop the insert issuing but it stops them from being persisted.
It used to be that an NHibernate session should always have an NHibernate transaction, even if there is an outer TransactionScope. It appears you don't. I haven't kept up to date with recent NH releases though - if this requirement has been relaxed or not.
I don't think a NH tx is necessary.
So, are you causing a timeout during your call to session.Flush(), and you believe that error somehow makes NH either unenlist the connection from the TransactionScope, or that NH in some way keeps using the connection after the TransactionScope has been somehow destroyed and the connection unenlisted?
The timeout is forced during Flush in my interceptor (you have to be picky where). NH keeps using the connection after the TransactionScope (or more accurately the ambient transaction) has timed out. How the heck that is possible is beyond me.
It used to be that an NHibernate session should always have an NHibernate transaction, even if there is an outer TransactionScope. It appears you don't. I haven't kept up to date with recent NH releases though - if this requirement has been relaxed or not.
The NHibernate Reference 12.8 says:
Instead of using NHibernate
ITransaction
,TransactionScope
can be used. Please do not use both simultaneously.
It used to be that an NHibernate session should always have an NHibernate transaction, even if there is an outer TransactionScope. It appears you don't. I haven't kept up to date with recent NH releases though - if this requirement has been relaxed or not.
From my view point such a recommendation has always been a mistake, whatever the NHibernate version. Using a NHibernate transaction opens a DbTransaction, and it is documented by Microsoft that one should not use a transaction scope and a DbTransaction simultaneously on the same connection.
I am currently facing this issue as well with transactions, using ISession.BeginTransaction(IsolationLevel)
Trying to rollback yields an exception with a message looking something like Not connected
Currently using NHibernate 5.2.3 Any updates on this issue at all?
This really looks to me like a trouble not bound to NHibernate. See this post on MSDN (requires a Microsoft account). It seems to be the exact same trouble, but without NHibernate.
If ambient transaction (TransactionScope) times out during a Flush, changes can still be affectuated to the database. The premisis is that the connection to SQL Server is in autocommit mode (which is default).
The attached code has two tests, NHibernateBug and ObservedBehavior. The former exposes what I have encountered by halting processing in a custom interceptor (MyInterceptor). The latter is my "looks-like-this-is-happening-in-NHibernate" analysis. Look in the output from the tests too.
You can run NHiberneateBug with the "#if !true" changed to "#if true" and see that SET IMPLICIT_TRANSACTIONS ON is a workaround to the inconsistency problem.