public void ParticipatingTransactionWithWithNotSupported() { IDbConnection connection = (IDbConnection)mocks.CreateMock(typeof(IDbConnection)); ISessionFactory sessionFactory = (ISessionFactory)mocks.CreateMock(typeof(ISessionFactory)); ISession session = (ISession)mocks.CreateMock(typeof(ISession)); ITransaction transaction = (ITransaction)mocks.CreateMock(typeof(ITransaction)); //using (mocks.Ordered()) //{ Expect.Call(sessionFactory.OpenSession()).Return(session).Repeat.Twice(); Expect.Call(session.Connection).Return(connection); Expect.Call(session.BeginTransaction(IsolationLevel.ReadCommitted)).Return(transaction); Expect.Call(session.IsOpen).Return(true); Expect.Call(session.FlushMode).Return(FlushMode.Auto).Repeat.Twice(); session.Flush(); LastCall.On(session).Repeat.Twice(); transaction.Commit(); LastCall.On(transaction).Repeat.Once(); #if NH_2_0 Expect.Call(session.Close()).Return(null).Repeat.Once(); #else Expect.Call(session.Close()).Return(null).Repeat.Twice(); #endif //} mocks.ReplayAll(); HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory); tm.TransactionSynchronization = TransactionSynchronizationState.Always; TransactionTemplate tt = new TransactionTemplate(tm); tt.PropagationBehavior = TransactionPropagation.RequiresNew; Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); tt.Execute(new ParticipatingTransactionWithWithNotSupportedTxCallback(tt, sessionFactory)); Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); mocks.VerifyAll(); }
/// <summary>The do get transaction.</summary> /// <returns>The System.Object.</returns> protected override object DoGetTransaction() { var transaction = new ResourcelessTransaction(); Stack <object> resources; if (!TransactionSynchronizationManager.HasResource(this)) { resources = new Stack <object>(); TransactionSynchronizationManager.BindResource(this, resources); } else { var stack = (Stack <object>)TransactionSynchronizationManager.GetResource(this); resources = stack; } resources.Push(transaction); return(transaction); }
public void TransactionRollbackOnly() { IDbConnection connection = (IDbConnection)mocks.CreateMock(typeof(IDbConnection)); ISessionFactory sessionFactory = (ISessionFactory)mocks.CreateMock(typeof(ISessionFactory)); ISession session = (ISession)mocks.CreateMock(typeof(ISession)); ITransaction transaction = (ITransaction)mocks.CreateMock(typeof(ITransaction)); IDbTransaction adoTransaction = (IDbTransaction)mocks.CreateMock(typeof(IDbTransaction)); using (mocks.Ordered()) { Expect.Call(sessionFactory.OpenSession()).Return(session); Expect.Call(session.Connection).Return(connection); Expect.Call(session.BeginTransaction(IsolationLevel.ReadCommitted)).Return(transaction); Expect.Call(session.IsOpen).Return(true); Expect.Call(session.FlushMode).Return(FlushMode.Auto); session.Flush(); LastCall.On(session).Repeat.Once(); Expect.Call(adoTransaction.Connection).Return(connection); LastCall.On(adoTransaction).Repeat.Once(); transaction.Rollback(); LastCall.On(transaction).Repeat.Once(); Expect.Call(session.Close()).Return(null); } mocks.ReplayAll(); TestableHibernateTransactionManager tm = new TestableHibernateTransactionManager(sessionFactory); tm.TransactionSynchronization = TransactionSynchronizationState.Always; tm.StubbedTransactionThatReturnsExpectedConnection = adoTransaction; TransactionTemplate tt = new TransactionTemplate(tm); Assert.IsFalse(TransactionSynchronizationManager.HasResource(sessionFactory), "Shouldn't have a thread session"); tt.Execute(new TransactionRollbackOnlyTxCallback(sessionFactory)); Assert.IsFalse(TransactionSynchronizationManager.HasResource(sessionFactory), "Shouldn't have a thread session"); mocks.VerifyAll(); }
public void SingleSessionAppliesDefaultFlushModeOnOpenSessionAndClosesSession() { ISession expectedSession = Fake <ISession>(); CallTo(() => expectedSessionFactory.OpenSession()).Returns(expectedSession); SessionScope scope = null; using (scope = new SessionScope(expectedSessionFactory, null, true, FlushMode.Auto, true)) { SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.GetResource(expectedSessionFactory); Assert.IsTrue(sessionHolder.ContainsSession(expectedSession)); } // ensure scope is closed and sessionHolder is unregistered from TSM Assert.IsFalse(scope.IsOpen); Assert.IsFalse(TransactionSynchronizationManager.HasResource(expectedSessionFactory)); CallToSet(() => expectedSession.FlushMode).WhenArgumentsMatch(x => x.Get <FlushMode>(0) == FlushMode.Auto).MustHaveHappenedOnceExactly(); CallTo(() => expectedSession.Close()).MustHaveHappenedOnceExactly(); }
public void SingleSessionRegistersSessionHolderWithTSM() { SessionScope scope = null; using (scope = new SessionScope(expectedSessionFactory, null, true, FlushMode.Auto, true)) { // ensure is open Assert.IsTrue(scope.IsOpen); Assert.IsFalse(scope.IsParticipating); // ensure registered sessionholder with TSM Assert.IsTrue(TransactionSynchronizationManager.HasResource(expectedSessionFactory)); // ensure a sessionHolder is registered SessionHolder sessionHolder = TransactionSynchronizationManager.GetResource(expectedSessionFactory) as SessionHolder; Assert.IsNotNull(sessionHolder); } // ensure scope is closed and sessionHolder is unregistered from TSM Assert.IsFalse(scope.IsOpen); Assert.IsFalse(TransactionSynchronizationManager.HasResource(expectedSessionFactory)); }
public void TransactionRollback() { IDbProvider provider = (IDbProvider)mocks.CreateMock(typeof(IDbProvider)); IDbConnection connection = (IDbConnection)mocks.CreateMock(typeof(IDbConnection)); ISessionFactory sessionFactory = (ISessionFactory)mocks.CreateMock(typeof(ISessionFactory)); ISession session = (ISession)mocks.CreateMock(typeof(ISession)); ITransaction transaction = (ITransaction)mocks.CreateMock(typeof(ITransaction)); using (mocks.Ordered()) { Expect.Call(sessionFactory.OpenSession()).Return(session); Expect.Call(session.Connection).Return(connection); Expect.Call(session.BeginTransaction(IsolationLevel.ReadCommitted)).Return(transaction); Expect.Call(session.IsOpen).Return(true); transaction.Rollback(); LastCall.On(transaction).Repeat.Once(); Expect.Call(session.Close()).Return(null); } mocks.ReplayAll(); HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory); TransactionTemplate tt = new TransactionTemplate(tm); Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active"); try { tt.Execute(new TransactionRollbackTxCallback(sessionFactory)); Assert.Fail("Should have thrown exception"); } catch (ArgumentException) { } Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); Assert.IsTrue(!TransactionSynchronizationManager.HasResource(provider), "Hasn't thread db provider"); mocks.VerifyAll(); }
public void TransactionWithPropagationSupports() { ISessionFactory sessionFactory = (ISessionFactory)mocks.CreateMock(typeof(ISessionFactory)); ISession session = (ISession)mocks.CreateMock(typeof(ISession)); Expect.Call(sessionFactory.OpenSession()).Return(session); Expect.Call(session.FlushMode).Return(FlushMode.Never); session.FlushMode = FlushMode.Auto; LastCall.IgnoreArguments(); session.Flush(); LastCall.IgnoreArguments(); session.FlushMode = FlushMode.Never; Expect.Call(session.FlushMode).Return(FlushMode.Never); #if NH_2_0 #else Expect.Call(session.Close()).Return(null); #endif mocks.ReplayAll(); LocalSessionFactoryObjectStub lsfo = new LocalSessionFactoryObjectStub(sessionFactory); lsfo.AfterPropertiesSet(); ISessionFactory sfProxy = (ISessionFactory)lsfo.GetObject(); Assert.IsNotNull(sfProxy); HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory); tm.TransactionSynchronization = TransactionSynchronizationState.Always; TransactionTemplate tt = new TransactionTemplate(tm); tt.PropagationBehavior = TransactionPropagation.Supports; Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); tt.Execute(new TransactionWithPropagationSupportsTxCallback(sessionFactory)); Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); mocks.VerifyAll(); }
public void ParticipatingTransactionWithWithRequiresNew() { DbConnection connection = A.Fake <DbConnection>(); ISessionFactory sessionFactory = A.Fake <ISessionFactory>(); ISession session1 = A.Fake <ISession>(); ISession session2 = A.Fake <ISession>(); ITransaction transaction = A.Fake <ITransaction>(); A.CallTo(() => sessionFactory.OpenSession()).Returns(session1).Once() .Then.Returns(session2).Once(); A.CallTo(() => session1.Connection).Returns(connection); A.CallTo(() => session1.BeginTransaction(IsolationLevel.ReadCommitted)).Returns(transaction); A.CallTo(() => session1.IsOpen).Returns(true); A.CallTo(() => session2.Connection).Returns(connection); A.CallTo(() => session2.BeginTransaction(IsolationLevel.ReadCommitted)).Returns(transaction); A.CallTo(() => session2.IsOpen).Returns(true); A.CallTo(() => session2.FlushMode).Returns(FlushMode.Auto); HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory); tm.TransactionSynchronization = TransactionSynchronizationState.Always; TransactionTemplate tt = new TransactionTemplate(tm); tt.PropagationBehavior = TransactionPropagation.RequiresNew; Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); tt.Execute(new ParticipatingTransactionWithWithRequiresNewTxCallback(tt, sessionFactory)); Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); A.CallTo(() => transaction.Commit()).MustHaveHappenedTwiceExactly(); A.CallTo(() => session2.Flush()).MustHaveHappenedOnceExactly(); A.CallTo(() => session1.Close()).MustHaveHappenedOnceExactly(); A.CallTo(() => session2.Close()).MustHaveHappenedOnceExactly(); }
public void TransactionRollback() { IDbProvider provider = A.Fake <IDbProvider>(); DbConnection connection = A.Fake <DbConnection>(); ISessionFactory sessionFactory = A.Fake <ISessionFactory>(); ISession session = A.Fake <ISession>(); ITransaction transaction = A.Fake <ITransaction>(); IDbTransaction adoTransaction = A.Fake <IDbTransaction>(); A.CallTo(() => sessionFactory.OpenSession()).Returns(session).Once(); A.CallTo(() => session.Connection).Returns(connection).Once(); A.CallTo(() => session.BeginTransaction(IsolationLevel.ReadCommitted)).Returns(transaction).Once(); A.CallTo(() => session.IsOpen).Returns(true).Once(); A.CallTo(() => adoTransaction.Connection).Returns(connection).Once(); TestableHibernateTransactionManager tm = new TestableHibernateTransactionManager(sessionFactory); tm.TransactionSynchronization = TransactionSynchronizationState.Always; tm.StubbedTransactionThatReturnsExpectedConnection = adoTransaction; TransactionTemplate tt = new TransactionTemplate(tm); Assert.IsFalse(TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); Assert.IsFalse(TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active"); try { tt.Execute(new TransactionRollbackTxCallback(sessionFactory)); Assert.Fail("Should have thrown exception"); } catch (ArgumentException) { } Assert.IsFalse(TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); Assert.IsFalse(TransactionSynchronizationManager.HasResource(provider), "Hasn't thread db provider"); A.CallTo(() => transaction.Rollback()).MustHaveHappened(); A.CallTo(() => session.Close()).MustHaveHappened(); }
public void SingleSessionAppliesDefaultFlushModeOnOpenSessionAndClosesSession() { ISession expectedSession = mocks.StrictMock <ISession>(); Expect.Call(expectedSessionFactory.OpenSession()).Return(expectedSession); expectedSession.FlushMode = FlushMode.Auto; Expect.Call(expectedSession.Close()).Return(null); mocks.ReplayAll(); SessionScope scope = null; using (scope = new SessionScope(expectedSessionFactory, null, true, FlushMode.Auto, true)) { SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.GetResource(expectedSessionFactory); Assert.IsTrue(sessionHolder.ContainsSession(expectedSession)); } // ensure scope is closed and sessionHolder is unregistered from TSM Assert.IsFalse(scope.IsOpen); Assert.IsFalse(TransactionSynchronizationManager.HasResource(expectedSessionFactory)); mocks.VerifyAll(); }
/// <summary> /// Return the current transaction object. /// </summary> /// <returns>The current transaction object.</returns> /// <exception cref="Spring.Transaction.CannotCreateTransactionException"> /// If transaction support is not available. /// </exception> /// <exception cref="Spring.Transaction.TransactionException"> /// In the case of lookup or system errors. /// </exception> protected override object DoGetTransaction() { HibernateTransactionObject txObject = new HibernateTransactionObject(); txObject.SavepointAllowed = NestedTransactionsAllowed; if (TransactionSynchronizationManager.HasResource(SessionFactory)) { SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.GetResource(SessionFactory); if (log.IsDebugEnabled) { log.Debug("Found thread-bound Session [" + sessionHolder.Session + "] for Hibernate transaction"); } txObject.SetSessionHolder(sessionHolder, false); if (DbProvider != null) { ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.GetResource(DbProvider); txObject.ConnectionHolder = conHolder; } } return(txObject); }
public void TransactionCommit() { IDbProvider provider = (IDbProvider)mocks.CreateMock(typeof(IDbProvider)); IDbConnection connection = (IDbConnection)mocks.CreateMock(typeof(IDbConnection)); ISessionFactory sessionFactory = (ISessionFactory)mocks.CreateMock(typeof(ISessionFactory)); ISession session = (ISession)mocks.CreateMock(typeof(ISession)); ITransaction transaction = (ITransaction)mocks.CreateMock(typeof(ITransaction)); IQuery query = (IQuery)mocks.CreateMock(typeof(IQuery)); IList list = new ArrayList(); list.Add("test"); using (mocks.Ordered()) { Expect.Call(sessionFactory.OpenSession()).Return(session); Expect.Call(session.Connection).Return(connection); Expect.Call(session.BeginTransaction(IsolationLevel.Serializable)).Return(transaction); Expect.Call(session.IsOpen).Return(true); Expect.Call(session.CreateQuery("some query string")).Return(query); Expect.Call(query.List()).Return(list); transaction.Commit(); LastCall.On(transaction).Repeat.Once(); Expect.Call(session.Close()).Return(null); } mocks.ReplayAll(); LocalSessionFactoryObjectStub lsfo = new LocalSessionFactoryObjectStub(sessionFactory); lsfo.AfterPropertiesSet(); ISessionFactory sfProxy = lsfo.GetObject() as ISessionFactory; Assert.IsNotNull(sfProxy); HibernateTransactionManager tm = new HibernateTransactionManager(); tm.TransactionSynchronization = TransactionSynchronizationState.Always; tm.AdoExceptionTranslator = new FallbackExceptionTranslator(); tm.SessionFactory = sfProxy; tm.DbProvider = provider; TransactionTemplate tt = new TransactionTemplate(tm); tt.TransactionIsolationLevel = IsolationLevel.Serializable; Assert.IsFalse(TransactionSynchronizationManager.HasResource(sfProxy), "Hasn't thread session"); Assert.IsFalse(TransactionSynchronizationManager.HasResource(provider), "Hasn't thread db provider"); Assert.IsFalse(TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active"); Assert.IsFalse(TransactionSynchronizationManager.ActualTransactionActive, "Actual transaction not active"); object result = tt.Execute(new TransactionCommitTxCallback(sfProxy, provider)); Assert.IsTrue(result == list, "Incorrect result list"); Assert.IsFalse(TransactionSynchronizationManager.HasResource(sfProxy), "Hasn't thread session"); Assert.IsFalse(TransactionSynchronizationManager.HasResource(provider), "Hasn't thread db provider"); Assert.IsFalse(TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active"); Assert.IsFalse(TransactionSynchronizationManager.ActualTransactionActive, "Actual transaction not active"); mocks.VerifyAll(); }
/// <summary> /// Does the test transaction commit with flush failure. /// </summary> /// <param name="fallbackTranslation">if set to <c>true</c> if the exception throw /// is of the type NHibernate.ADOException, in which case HibernateTransactionManager /// will 'fallback' to using the error codes in the underlying exception thrown by /// the provider, ie. a SqlException, MySqlException. Otherwise, if it is /// another subclass of HibernateException, then perform a direct maping as /// found in SessionFactoryUtils.ConvertHibernateAccessException.</param> private void DoTransactionCommitWithFlushFailure(bool fallbackTranslation) { #region Mock Setup IDbProvider provider = new TestDbProvider(); IDbConnection connection = (IDbConnection)mocks.CreateMock(typeof(IDbConnection)); ISessionFactory sessionFactory = (ISessionFactory)mocks.CreateMock(typeof(ISessionFactory)); ISession session = (ISession)mocks.CreateMock(typeof(ISession)); ITransaction transaction = (ITransaction)mocks.CreateMock(typeof(ITransaction)); IDbTransaction adoTransaction = (IDbTransaction)mocks.CreateMock(typeof(IDbTransaction)); Exception rootCause = null; using (mocks.Ordered()) { Expect.Call(sessionFactory.OpenSession()).Return(session); Expect.Call(session.Connection).Return(connection); Expect.Call(session.BeginTransaction(IsolationLevel.ReadCommitted)).Return(transaction); Expect.Call(session.IsOpen).Return(true); transaction.Commit(); Exception sqlException = new TestSqlException("mymsg", "2627"); if (fallbackTranslation) { //error code 2627 will map to a DataAccessIntegrity exception in sqlserver, which is the metadata //used by TestDbProvider. rootCause = sqlException; LastCall.On(transaction).Throw(new ADOException("mymsg", sqlException)); } else { #if NH_2_0 || NH_2_1 rootCause = new PropertyValueException("mymsg", typeof(string).Name, "Name"); #else rootCause = new PropertyValueException("mymsg", typeof(string), "Name"); #endif LastCall.On(transaction).Throw(rootCause); } Expect.Call(adoTransaction.Connection).Return(connection); LastCall.On(adoTransaction).Repeat.Once(); transaction.Rollback(); LastCall.On(transaction).Repeat.Once(); Expect.Call(session.Close()).Return(null); } #endregion mocks.ReplayAll(); TestableHibernateTransactionManager tm = new TestableHibernateTransactionManager(sessionFactory); tm.TransactionSynchronization = TransactionSynchronizationState.Always; tm.DbProvider = provider; tm.StubbedTransactionThatReturnsExpectedConnection = adoTransaction; TransactionTemplate tt = new TransactionTemplate(tm); Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active"); IList list = new ArrayList(); list.Add("test"); try { tt.Execute(new TransactionCommitWithFlushFailureCallback(sessionFactory, list)); Assert.Fail("Should have thrown DataIntegrityViolationException"); } catch (DataIntegrityViolationException ex) { Assert.AreEqual(rootCause, ex.InnerException); Assert.IsTrue(ex.Message.IndexOf("mymsg") != -1); } Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active"); mocks.VerifyAll(); }
public void TransactionWithPropagationSupportsAndInnerTransaction() { IDbConnection connection = (IDbConnection)mocks.CreateMock(typeof(IDbConnection)); ISessionFactory sessionFactory = (ISessionFactory)mocks.CreateMock(typeof(ISessionFactory)); ISession session1 = (ISession)mocks.CreateMock(typeof(ISession)); ISession session2 = (ISession)mocks.CreateMock(typeof(ISession)); ITransaction transaction = (ITransaction)mocks.CreateMock(typeof(ITransaction)); Expect.Call(sessionFactory.OpenSession()).Return(session1); Expect.Call(session1.Connection).Return(connection); Expect.Call(session1.SessionFactory).Return(sessionFactory); Expect.Call(session1.FlushMode).Return(FlushMode.Auto).Repeat.Twice(); session1.Flush(); LastCall.IgnoreArguments().Repeat.Twice(); Expect.Call(session1.Close()).Return(null); Expect.Call(sessionFactory.OpenSession()).Return(session2); Expect.Call(session2.Connection).Return(connection).Repeat.Twice(); Expect.Call(session2.BeginTransaction(IsolationLevel.ReadCommitted)).Return(transaction); Expect.Call(session2.FlushMode).Return(FlushMode.Auto); session2.Flush(); LastCall.IgnoreArguments(); Expect.Call(session2.IsOpen).Return(true); transaction.Commit(); LastCall.On(transaction).Repeat.Once(); Expect.Call(session2.Close()).Return(null); mocks.ReplayAll(); LocalSessionFactoryObjectStub lsfo = new LocalSessionFactoryObjectStub(sessionFactory); lsfo.AfterPropertiesSet(); ISessionFactory sfProxy = (ISessionFactory)lsfo.GetObject(); Assert.IsNotNull(sfProxy); HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory); tm.TransactionSynchronization = TransactionSynchronizationState.Always; TransactionTemplate tt = new TransactionTemplate(tm); tt.PropagationBehavior = TransactionPropagation.Supports; TransactionTemplate tt2 = new TransactionTemplate(tm); tt2.PropagationBehavior = TransactionPropagation.Required; HibernateTemplate ht = new HibernateTemplate(sessionFactory); ht.TemplateFlushMode = TemplateFlushMode.Eager; ht.ExposeNativeSession = true; Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); tt.Execute(new TransactionWithPropagationSupportsAndInnerTransactionTxCallback(tt2, sessionFactory, ht, session1, session2)); Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); mocks.ReplayAll(); }
/// <summary> /// Begin a new transaction with the given transaction definition. /// </summary> /// <param name="transaction"> /// Transaction object returned by /// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager.DoGetTransaction"/>. /// </param> /// <param name="definition"> /// <see cref="Spring.Transaction.ITransactionDefinition"/> instance, describing /// propagation behavior, isolation level, timeout etc. /// </param> /// <remarks> /// Does not have to care about applying the propagation behavior, /// as this has already been handled by this abstract manager. /// </remarks> /// <exception cref="Spring.Transaction.TransactionException"> /// In the case of creation or system errors. /// </exception> protected override void DoBegin(object transaction, ITransactionDefinition definition) { TxScopeTransactionManager.PromotableTxScopeTransactionObject promotableTxScopeTransactionObject = ((HibernateTransactionObject)transaction).PromotableTxScopeTransactionObject; try { DoTxScopeBegin(promotableTxScopeTransactionObject, definition); } catch (Exception e) { throw new CannotCreateTransactionException("Transaction Scope failure on begin", e); } HibernateTransactionObject txObject = (HibernateTransactionObject)transaction; if (DbProvider != null && TransactionSynchronizationManager.HasResource(DbProvider) && !txObject.ConnectionHolder.SynchronizedWithTransaction) { throw new IllegalTransactionStateException( "Pre-bound ADO.NET Connection found - HibernateTransactionManager does not support " + "running within AdoTransactionManager if told to manage the DbProvider itself. " + "It is recommended to use a single HibernateTransactionManager for all transactions " + "on a single DbProvider, no matter whether Hibernate or ADO.NET access."); } ISession session = null; try { if (txObject.SessionHolder == null || txObject.SessionHolder.SynchronizedWithTransaction) { IInterceptor interceptor = EntityInterceptor; ISession newSession = (interceptor != null ? SessionFactory.OpenSession(interceptor) : SessionFactory.OpenSession()); if (log.IsDebugEnabled) { log.Debug("Opened new Session [" + newSession + "] for Hibernate transaction"); } txObject.SetSessionHolder(new SessionHolder(newSession), true); } txObject.SessionHolder.SynchronizedWithTransaction = true; session = txObject.SessionHolder.Session; IDbConnection con = session.Connection; //TODO isolation level mgmt //IsolationLevel previousIsolationLevel = if (definition.ReadOnly && txObject.NewSessionHolder) { // Just set to NEVER in case of a new Session for this transaction. session.FlushMode = FlushMode.Never; } if (!definition.ReadOnly && !txObject.NewSessionHolder) { // We need AUTO or COMMIT for a non-read-only transaction. FlushMode flushMode = session.FlushMode; if (FlushMode.Never == flushMode) { session.FlushMode = FlushMode.Auto; txObject.SessionHolder.PreviousFlushMode = flushMode; } } // Add the Hibernate transaction to the session holder. // for now pass in tx options isolation level. ITransaction hibernateTx = session.BeginTransaction(definition.TransactionIsolationLevel); IDbTransaction adoTx = GetIDbTransaction(hibernateTx); // Add the Hibernate transaction to the session holder. txObject.SessionHolder.Transaction = hibernateTx; // Register transaction timeout. int timeout = DetermineTimeout(definition); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { txObject.SessionHolder.TimeoutInSeconds = timeout; } // Register the Hibernate Session's ADO.NET Connection/TX pair for the DbProvider, if set. if (DbProvider != null) { //investigate passing null for tx. ConnectionHolder conHolder = new ConnectionHolder(con, adoTx); if (timeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT) { conHolder.TimeoutInMillis = definition.TransactionTimeout; } if (log.IsDebugEnabled) { log.Debug("Exposing Hibernate transaction as ADO transaction [" + con + "]"); } TransactionSynchronizationManager.BindResource(DbProvider, conHolder); txObject.ConnectionHolder = conHolder; } // Bind the session holder to the thread. if (txObject.NewSessionHolder) { TransactionSynchronizationManager.BindResource(SessionFactory, txObject.SessionHolder); } } catch (Exception ex) { SessionFactoryUtils.CloseSession(session); throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); } }
/// <summary> /// Does the test transaction commit with flush failure. /// </summary> /// <param name="fallbackTranslation">if set to <c>true</c> if the exception throw /// is of the type NHibernate.ADOException, in which case HibernateTransactionManager /// will 'fallback' to using the error codes in the underlying exception thrown by /// the provider, ie. a SqlException, MySqlException. Otherwise, if it is /// another subclass of HibernateException, then perform a direct maping as /// found in SessionFactoryUtils.ConvertHibernateAccessException.</param> private void DoTransactionCommitWithFlushFailure(bool fallbackTranslation) { IDbProvider provider = new TestDbProvider(); DbConnection connection = A.Fake <DbConnection>(); ISessionFactory sessionFactory = A.Fake <ISessionFactory>(); ISession session = A.Fake <ISession>(); ITransaction transaction = A.Fake <ITransaction>(); IDbTransaction adoTransaction = A.Fake <IDbTransaction>(); Exception rootCause; A.CallTo(() => sessionFactory.OpenSession()).Returns(session); A.CallTo(() => session.Connection).Returns(connection); A.CallTo(() => session.BeginTransaction(IsolationLevel.ReadCommitted)).Returns(transaction); A.CallTo(() => session.IsOpen).Returns(true); Exception sqlException = new TestSqlException("mymsg", "2627"); if (fallbackTranslation) { //error code 2627 will map to a DataAccessIntegrity exception in sqlserver, which is the metadata //used by TestDbProvider. rootCause = sqlException; A.CallTo(() => transaction.Commit()).Throws(new ADOException("mymsg", sqlException)); } else { rootCause = new PropertyValueException("mymsg", typeof(string).Name, "Name"); A.CallTo(() => transaction.Commit()).Throws(rootCause); } A.CallTo(() => adoTransaction.Connection).Returns(connection).Once(); TestableHibernateTransactionManager tm = new TestableHibernateTransactionManager(sessionFactory); tm.TransactionSynchronization = TransactionSynchronizationState.Always; tm.DbProvider = provider; tm.StubbedTransactionThatReturnsExpectedConnection = adoTransaction; TransactionTemplate tt = new TransactionTemplate(tm); Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active"); IList list = new ArrayList(); list.Add("test"); try { tt.Execute(new TransactionCommitWithFlushFailureCallback(sessionFactory, list)); Assert.Fail("Should have thrown DataIntegrityViolationException"); } catch (DataIntegrityViolationException ex) { Assert.AreEqual(rootCause, ex.InnerException); Assert.IsTrue(ex.Message.IndexOf("mymsg") != -1); } Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session"); Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active"); A.CallTo(() => transaction.Rollback()).MustHaveHappenedOnceExactly(); A.CallTo(() => session.Close()).MustHaveHappenedOnceExactly(); }