-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: TransactionScope no longer works in Beta3
PostPosted: Fri Jan 12, 2007 4:20 pm 
Newbie

Joined: Thu Dec 14, 2006 11:14 pm
Posts: 6
Session management has changed in NHibernate 1.2 Beta3 in a way that seems to prevent the use of System.Transaction.TransactionScope.

I was using Beta2 and successfully embedding NHibernate code inside a TransactionScope as long as the Session was not used prior to the TransactionScope block. Example:
Code:
     using (System.Transactions.TransactionScope transScope = new System.Transactions.TransactionScope())
          {
               session = NHibernateHelper.GetCurrentSession();

               ...work with the session...

               session.Flush();
               transScope.Complete();
          }

However, Beta3 introduces a concept of AggressiveRelease in the new ConnectionManager class. This only seems to be aware of Transactions that are programmatically managed by
Code:
     session.BeginTransaction()

If session operations are performed inside a TransactionScope, the AggressiveRelease determines that it should still AutoClose the session since it doesn't believe there is a current transaction. In Beta2, the IsInActiveTransaction (on SessionImpl in that code base) was only called on disconnect.

Is this change by design, or is there an intention to support TransactionScope in which case this is probably a regression bug? I hestitated filing a JIRA bug because I haven't seen explicit NHibernate documentation indicating support for .NET 2.0's System.Transactions, although it appeared to have been working fine in Beta2 and it seems that other people on this newsgroup were using it in the way I described above.

Obviously there might be more significant changes needed, but maybe you could just change the ConnectionManager.IsInActiveTransaction from:
Code:
     public bool IsInActiveTransaction
     {
          get { return transaction != null && transaction.IsActive; }
     }

to something like:
Code:
     public bool IsInActiveTransaction
     {
          get
          {
               bool inTransaction = transaction != null && transaction.IsActive;
               bool inTransaction |= (System.Transactions.Transaction.Current != null);
               return inTransaction;
          }
     }

I have no idea if that is the best way to achieve the result and it introduces a compile-time dependency on System.Transactions which might not be appropriate, but it's just some food for thought.

Thanks.

Pete


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 12, 2007 4:50 pm 
Beginner
Beginner

Joined: Thu Dec 21, 2006 11:38 am
Posts: 30
I hope the implementors will also allow for TransactionScope to operate...

I'm beginning to use transactionscope everywhere for allowing business objects to participate in or start transactions in their contexts.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 12, 2007 5:09 pm 
Newbie

Joined: Thu Dec 14, 2006 11:14 pm
Posts: 6
Despite the length of my previous post, I think I might not have been clear about the error that I was actually getting.

If I put more than 1 interaction with the session inside a TransactionScope, I get an exception (running against MS SQL2005). This is because the first interaction with the session opens a connection that is implicitly associated with the TransactionScope. However, this session's DB connection is automatically closed, so the next interaction with that same session causes a NEW DB connection to be opened which would require elevating the transaction to a distributed transaction and I am not running the Microsoft Distributed Transaction Coordinator. Therefore the following exception occurs:

Code:
"System.Data.SqlClient.SqlException: MSDTC on server '...' is unavailable.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
   at System.Data.SqlClient.SqlDataReader.get_MetaData()
   at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.GetDTCAddress(Int32 timeout, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlInternalConnectionTds.GetDTCAddress()
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at NHibernate.Connection.DriverConnectionProvider.GetConnection() in c:\\net\\nhibernate\\nhibernate\\src\\NHibernate\\Connection\\DriverConnectionProvider.cs:line 46
   at NHibernate.Impl.SessionFactoryImpl.OpenConnection() in c:\\net\\nhibernate\\nhibernate\\src\\NHibernate\\Impl\\SessionFactoryImpl.cs:line 1159"


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 12, 2007 8:13 pm 
Contributor
Contributor

Joined: Sat Sep 24, 2005 11:25 am
Posts: 198
Okay, that is actually an expected error, and the way it should work.
The issue here is that when NHibernate is opening the connection again, the current transaction is escalated from local transaction to distributed one (because there is more than a single connection), this requires an available transaction server, naturally.

The work-around is to use release_mode = "on_close".

I am not sure that this is a real word around or the way it should be.
Please open a JIRA for this issue.

You suggested fix seems reasonable, and look at the source doesn't seem to bring any issues.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 14, 2007 5:04 pm 
Newbie

Joined: Thu Dec 14, 2006 11:14 pm
Posts: 6
Thanks for the pointer to the release_mode which, as you said, does provide a workaround by disabling the newly introduced AggressiveRelease logic.

Per your suggestion, I created a JIRA issue (http://jira.nhibernate.org/browse/NH-861) with the hope that a more robust fix can be made.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.