Uploaded image for project: 'Spring.NET'
  1. Spring.NET
  2. SPRNET-1438

Extraneous NHibernate Session created and used for transactions that begin in the scope of TransactionPropagation.Supports with OpenSessionInViewModule or SessionScope

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 1.1.0, 1.1.1, 1.1.2, 1.2.0, 1.3.1
    • Fix Version/s: 1.3.2
    • Labels:
      None
    • Environment:
      - Windows Server 2008 R2, SQL Server 2008, Spring.NET 1.3.1, NHibernate 3.0.0.GA
      - Windows XP SP3, SQL Server 2005, Spring.NET 1.1.2, NHibernate 2.0.0

      Description

      (see linked forum posting for most details)

      OpenSessionInViewModule (OSIV) and SessionScope are supposed to guarantee session-per-unit-of-work, such that the unit of work (UoW) for OSIV is the request, and for SessionScope is the scope of the {{using(new SessionScope(...))

      {...}

      }} statement.

      However, if you go from no-transaction-demarcation to transaction-supports-demarcation to transaction-required-demarcation, a new NHibernate session will be created and used for the scope of the transaction-required work rather than the single thread-bound session.

      The problem seems to be in the DoBegin method of either the HibernateTransactionManager or the HibernateTxScopeTransactionManager. The line of code that guards the section where a new session will be created when beginning a new transaction will evaluate to true if the call came from within a TransactionPropagation.Supports scope.

      if (txObject.SessionHolder == null || txObject.SessionHolder.SynchronizedWithTransaction)

      { /* opens new session */ }

      This is because when entering TransactionPropagtion.Supports, the SessionHolder.SynchronizedWithTransaction is set to true, even if there is no existing transaction to support. I suspect the bug lies either in flagging that as true, or in the incomplete way the transactional state is evaluated in the above condition. I suggest trying to make this check more explicit by looking to see if an actual transaction has been created yet, like so:

      if (txObject.SessionHolder == null || (txObject.SessionHolder.SynchronizedWithTransaction && TransactionSynchronizationManager.ActualTransactionActive))

      This behavior does have some bad side-effects, like "invalid attempt to associate a collection with two open sessions", so the sooner it's cleaned up the better (see forum posting for more side effects).

      A sample app that demos the behavior and error based on the Spring.Data.NHibernate.Northwind example is attached (see forum post for more details).
      1. Download, unzip, build sln, play (debug)
      2. customer list > orders > view order details > increment quantity: you will see stat of extra session created
      3. customer list > orders > process orders > back to customer order list > return orders: you will see "collection in two open sessions" error

        • If you do #3 with the HibernateTxScopeTransactionManager, you will get a different error, which seems related to SPRNET-1410

      NOTE: The code is the same way in the latest version of Java's HibernateTransactionManager, so this bug may exist there too.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                sbohlen Steve Bohlen
                Reporter:
                khickey Keith Hickey
              • Votes:
                2 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - 2d
                  2d
                  Remaining:
                  Remaining Estimate - 2d
                  2d
                  Logged:
                  Time Spent - Not Specified
                  Not Specified