diff --git a/test/Spring/Spring.SessionFactoryImplError.Tests/CustomSpring132HibernateTxScopeTransactionManager.cs b/test/Spring/Spring.SessionFactoryImplError.Tests/CustomSpring132HibernateTxScopeTransactionManager.cs
deleted file mode 100644
index 009f5299..00000000
--- a/test/Spring/Spring.SessionFactoryImplError.Tests/CustomSpring132HibernateTxScopeTransactionManager.cs
+++ /dev/null
@@ -1,1168 +0,0 @@
-using System;
-using System.Data;
-using System.Reflection;
-using System.Transactions;
-using NHibernate;
-using NHibernate.Transaction;
-using Spring.Core.TypeResolution;
-using Spring.Dao;
-using Spring.Data.Common;
-using Spring.Data.Core;
-using Spring.Data.NHibernate;
-using Spring.Data.Support;
-using Spring.Objects.Factory;
-using Spring.Transaction;
-using Spring.Transaction.Support;
-using HibernateTransactionException = NHibernate.TransactionException;
-
-namespace Spring.SessionFactoryImplError.Tests
-{
- ///
- /// A complete copy and selective re-write of the Spring.Data.NHibernate. from the Spring.Data.NHibernate32 DLL
- /// to patch bugs with their implementation that could not be rectified by overriding the class (due to so much private scoping).
- ///
- ///
- /// This will be committed to source control in its first version the same way as it appeared in the Spring.NET v1.3.2 (.NET v4.0, VS 2010) source code; therefore, changes
- /// from the base version in v1.3.2 will be discernable from source control. Those changes will need to be ported to the version of the
- /// in the next upgrade of Spring.NET, and so forth. A new copy of that versions HibernateTxScopeTransactionManager will need to be copied into a CustomSpring132HibernateTxScopeTransactionManager
- /// file, that should be committed, then the changes need to be ported. This should continue until Spring's version is bug-free.
- ///
- public class CustomSpring132HibernateTxScopeTransactionManager : AbstractPlatformTransactionManager, IResourceTransactionManager, IObjectFactoryAware, IInitializingObject
- {
- #region Fields
-
- private ISessionFactory sessionFactory;
-
- private IDbProvider dbProvider;
-
- private bool autodetectDbProvider = true;
-
- private Object entityInterceptor;
-
- private IAdoExceptionTranslator adoExceptionTranslator;
-
- private IAdoExceptionTranslator defaultExceptionTranslator;
-
- ///
- /// Just needed for entityInterceptorBeanName.
- ///
- private IObjectFactory objectFactory;
-
- private TxScopeTransactionManager txScopeTranactionManager;
-
- private static readonly MethodInfo SessionFactoryUtils_CloseSessionOrRegisterDeferredClose_Method;
-
- #endregion
-
- #region Constructor (s)
-
- ///
- /// Static constructor to get a handle to a internal method from a spring assembly that is needed in this assembly.
- ///
- static CustomSpring132HibernateTxScopeTransactionManager()
- {
- Type sfuType = typeof (SessionFactoryUtils);
- SessionFactoryUtils_CloseSessionOrRegisterDeferredClose_Method = sfuType.GetMethod("CloseSessionOrRegisterDeferredClose", BindingFlags.Static | BindingFlags.NonPublic);
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public CustomSpring132HibernateTxScopeTransactionManager()
- {
- txScopeTranactionManager = new TxScopeTransactionManager();
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The session factory.
- public CustomSpring132HibernateTxScopeTransactionManager(ISessionFactory sessionFactory)
- {
- this.sessionFactory = sessionFactory;
- AfterPropertiesSet();
- }
-
- #endregion
-
- #region Properties
-
- ///
- /// Gets or sets the db provider.
- ///
- /// The db provider.
- public IDbProvider DbProvider
- {
- get { return dbProvider; }
- set { dbProvider = value; }
- }
-
- ///
- /// Gets or sets a Hibernate entity interceptor that allows to inspect and change
- /// property values before writing to and reading from the database.
- /// When getting, return the current Hibernate entity interceptor, or null if none.
- ///
- /// The entity interceptor.
- ///
- /// Resolves an entity interceptor object name via the object factory,
- /// if necessary.
- /// Will get applied to any new Session created by this transaction manager.
- /// Such an interceptor can either be set at the SessionFactory level,
- /// i.e. on LocalSessionFactoryObject, or at the Session level, i.e. on
- /// HibernateTemplate, HibernateInterceptor, and HibernateTransactionManager.
- /// It's preferable to set it on LocalSessionFactoryObject or HibernateTransactionManager
- /// to avoid repeated configuration and guarantee consistent behavior in transactions.
- ///
- /// If object factory is null and need to get entity interceptor via object name.
- public IInterceptor EntityInterceptor
- {
- get
- {
- if (this.entityInterceptor is IInterceptor)
- {
- return (IInterceptor)entityInterceptor;
- }
- else if (this.entityInterceptor is string)
- {
- if (this.objectFactory == null)
- {
- throw new InvalidOperationException("Cannot get entity interceptor via object name if no object factory set");
- }
- String objectName = (String)this.entityInterceptor;
- return (IInterceptor)this.objectFactory.GetObject(objectName, typeof(IInterceptor));
- }
- else
- {
- return null;
- }
- }
- set
- {
- entityInterceptor = value;
- }
- }
-
- ///
- /// Sets the object name of a Hibernate entity interceptor that
- /// allows to inspect and change property values before writing to and reading from the database.
- ///
- /// The name of the entity interceptor object.
- ///
- /// Will get applied to any new Session created by this transaction manager.
- ///
Requires the object factory to be known, to be able to resolve the object
- /// name to an interceptor instance on session creation. Typically used for
- /// prototype interceptors, i.e. a new interceptor instance per session.
- ///
- ///
Can also be used for shared interceptor instances, but it is recommended
- /// to set the interceptor reference directly in such a scenario.
- ///
- ///
- public string EntityInterceptorObjectName
- {
- set
- {
- entityInterceptor = value;
- }
- }
-
- ///
- /// Gets or sets the ADO.NET exception translator for this transaction manager.
- ///
- ///
- /// Applied to ADO.NET Exceptions (wrapped by Hibernate's ADOException)
- ///
- /// The ADO exception translator.
- public IAdoExceptionTranslator AdoExceptionTranslator
- {
- get { return adoExceptionTranslator; }
- set { adoExceptionTranslator = value; }
- }
-
- ///
- /// Gets the default IAdoException translator, lazily creating it if nece
- ///
- /// The default IAdoException translator.
- public IAdoExceptionTranslator DefaultAdoExceptionTranslator
- {
- get
- {
- lock (this)
- {
- if (defaultExceptionTranslator == null)
- {
- if (dbProvider != null)
- {
- defaultExceptionTranslator = new ErrorCodeExceptionTranslator(dbProvider);
- }
- else
- {
- defaultExceptionTranslator = SessionFactoryUtils.NewAdoExceptionTranslator(SessionFactory);
- }
- }
- return defaultExceptionTranslator;
- }
- }
- }
-
- ///
- /// Gets or sets the SessionFactory that this instance should manage transactions for.
- ///
- /// The session factory.
- public ISessionFactory SessionFactory
- {
- get { return sessionFactory; }
- set { sessionFactory = value; }
- }
-
-
- ///
- /// Gets the resource factory that this transaction manager operates on,
- /// For the HibenratePlatformTransactionManager this the SessionFactory
- ///
- /// The SessionFactory.
- public object ResourceFactory
- {
- get { return sessionFactory; }
- }
-
- ///
- /// Set whether to autodetect a ADO.NET connection used by the Hibernate SessionFactory,
- /// if set via LocalSessionFactoryObject's DbProvider. Default is "true".
- ///
- ///
- /// true if [autodetect data source]; otherwise, false.
- ///
- ///
- ///
Can be turned off to deliberately ignore an available IDbProvider,
- /// to not expose Hibernate transactions as ADO.NET transactions for that IDbProvider.
- ///
- ///
- public bool AutodetectDbProvider
- {
- set { autodetectDbProvider = value; }
- }
-
- #endregion
-
- #region Methods
-
- #endregion
-
-
- ///
- /// The object factory just needs to be known for resolving entity interceptor
- /// It does not need to be set for any other mode of operation.
- ///
- ///
- /// Owning
- /// (may not be ). The object can immediately
- /// call methods on the factory.
- ///
- public IObjectFactory ObjectFactory
- {
- set
- {
- objectFactory = value;
- }
- }
-
- ///
- /// Return the current transaction object.
- ///
- /// The current transaction object.
- ///
- /// If transaction support is not available.
- ///
- ///
- /// In the case of lookup or system errors.
- ///
- protected override object DoGetTransaction()
- {
- if (log.IsDebugEnabled)
- {
- if (System.Transactions.Transaction.Current == null)
- {
- log.Debug("DoGetTransaction: No transaction currently exists");
- }
- else
- {
- log.Debug(string.Format("DoGetTransaction: Getting transaction object for existing System.Transactions.Transaction{0}", WriteTransactionInformation(System.Transactions.Transaction.Current)));
- }
- }
-
- 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;
- }
- }
- txObject.PromotableTxScopeTransactionObject = new TxScopeTransactionManager.PromotableTxScopeTransactionObject();
-
- return txObject;
- }
-
- ///
- /// Check if the given transaction object indicates an existing,
- /// i.e. already begun, transaction.
- ///
- ///
- /// Transaction object returned by
- /// .
- ///
- /// True if there is an existing transaction.
- ///
- /// In the case of system errors.
- ///
- protected override bool IsExistingTransaction(object transaction)
- {
- return
- ((HibernateTransactionObject)transaction).PromotableTxScopeTransactionObject.TxScopeAdapter.
- IsExistingTransaction &&
- ((HibernateTransactionObject) transaction).HasTransaction();
- }
-
- ///
- /// Begin a new transaction with the given transaction definition.
- ///
- ///
- /// Transaction object returned by
- /// .
- ///
- ///
- /// instance, describing
- /// propagation behavior, isolation level, timeout etc.
- ///
- ///
- /// Does not have to care about applying the propagation behavior,
- /// as this has already been handled by this abstract manager.
- ///
- ///
- /// In the case of creation or system errors.
- ///
- 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);
- }
-
- if (log.IsDebugEnabled)
- {
- log.Debug(string.Format("DoBegin: Began new System.Transactions.Transaction{0}", WriteTransactionInformation(System.Transactions.Transaction.Current)));
- }
-
- 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;
- try
- {
- con = session.Connection;
- //TODO isolation level mgmt
- //IsolationLevel previousIsolationLevel =
- }
- catch (System.Data.SqlClient.SqlException ex)
- {
- // Retry logic as a workaround for ADO.NET 2.0 vulnerabilty: KB916002 and MS Connect bug 93731
- if (ex.Message.Contains("New request is not allowed to start because it should come with valid transaction descriptor"))
- {
- if (log.IsWarnEnabled)
- {
- log.Warn("Forced to clear all SQL connection pools due to corrupted transaction context on a connection from the connection pool (KB916002).");
- }
- System.Data.SqlClient.SqlConnection.ClearAllPools();
- con = session.Connection;
- }
- else
- {
- throw;
- }
- }
-
- 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);
- }
-
-
- }
-
- private void DoTxScopeBegin(TxScopeTransactionManager.PromotableTxScopeTransactionObject txObject,
- Spring.Transaction.ITransactionDefinition definition)
- {
-
- TransactionScopeOption txScopeOption = CreateTransactionScopeOptions(definition);
- TransactionOptions txOptions = CreateTransactionOptions(definition);
- txObject.TxScopeAdapter.CreateTransactionScope(txScopeOption, txOptions, definition.EnterpriseServicesInteropOption);
-
- }
-
- private static TransactionScopeOption CreateTransactionScopeOptions(ITransactionDefinition definition)
- {
- TransactionScopeOption txScopeOption;
- if (definition.PropagationBehavior == TransactionPropagation.Required)
- {
- txScopeOption = TransactionScopeOption.Required;
- }
- else if (definition.PropagationBehavior == TransactionPropagation.RequiresNew)
- {
- txScopeOption = TransactionScopeOption.RequiresNew;
- }
- else if (definition.PropagationBehavior == TransactionPropagation.NotSupported)
- {
- txScopeOption = TransactionScopeOption.Suppress;
- }
- else
- {
- throw new Spring.Transaction.TransactionSystemException("Transaction Propagation Behavior" +
- definition.PropagationBehavior +
- " not supported by TransactionScope. Use Required or RequiredNew");
- }
- return txScopeOption;
- }
-
-
- private static TransactionOptions CreateTransactionOptions(ITransactionDefinition definition)
- {
- TransactionOptions txOptions = new TransactionOptions();
- switch (definition.TransactionIsolationLevel)
- {
- case System.Data.IsolationLevel.Chaos:
- txOptions.IsolationLevel = System.Transactions.IsolationLevel.Chaos;
- break;
- case System.Data.IsolationLevel.ReadCommitted:
- txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
- break;
- case System.Data.IsolationLevel.ReadUncommitted:
- txOptions.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted;
- break;
- case System.Data.IsolationLevel.RepeatableRead:
- txOptions.IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead;
- break;
- case System.Data.IsolationLevel.Serializable:
- txOptions.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
- break;
- case System.Data.IsolationLevel.Snapshot:
- txOptions.IsolationLevel = System.Transactions.IsolationLevel.Snapshot;
- break;
- case System.Data.IsolationLevel.Unspecified:
- txOptions.IsolationLevel = System.Transactions.IsolationLevel.Unspecified;
- break;
- }
-
- if (definition.TransactionTimeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
- {
- txOptions.Timeout = new TimeSpan(0, 0, definition.TransactionTimeout);
- }
- return txOptions;
- }
-
-
-
- ///
- /// Suspend the resources of the current transaction.
- ///
- ///
- /// Transaction object returned by
- /// .
- ///
- ///
- /// An object that holds suspended resources (will be kept unexamined for passing it into
- /// .)
- ///
- ///
- /// Transaction synchronization will already have been suspended.
- ///
- ///
- /// If suspending is not supported by the transaction manager implementation.
- ///
- ///
- /// in case of system errors.
- ///
- protected override object DoSuspend(object transaction)
- {
- HibernateTransactionObject txObject = (HibernateTransactionObject)transaction;
- txObject.SetSessionHolder(null, false);
- SessionHolder sessionHolder =
- (SessionHolder)TransactionSynchronizationManager.UnbindResource(SessionFactory);
- ConnectionHolder connectionHolder = null;
- if (DbProvider != null)
- {
- connectionHolder = (ConnectionHolder)TransactionSynchronizationManager.UnbindResource(DbProvider);
- }
- return new SuspendedResourcesHolder(sessionHolder, connectionHolder);
-
- }
-
- ///
- /// Resume the resources of the current transaction.
- ///
- ///
- /// Transaction object returned by
- /// .
- ///
- ///
- /// The object that holds suspended resources as returned by
- /// .
- ///
- ///
- /// Transaction synchronization will be resumed afterwards.
- ///
- ///
- /// If suspending is not supported by the transaction manager implementation.
- ///
- ///
- /// In the case of system errors.
- ///
- protected override void DoResume(object transaction, object suspendedResources)
- {
- SuspendedResourcesHolder resourcesHolder = (SuspendedResourcesHolder)suspendedResources;
- if (TransactionSynchronizationManager.HasResource(SessionFactory))
- {
- // From non-transactional code running in active transaction synchronization
- // -> can be safely removed, will be closed on transaction completion.
- TransactionSynchronizationManager.UnbindResource(SessionFactory);
- }
- TransactionSynchronizationManager.BindResource(SessionFactory, resourcesHolder.SessionHolder);
- if (DbProvider != null)
- {
- TransactionSynchronizationManager.BindResource(DbProvider, resourcesHolder.ConnectionHolder);
- }
- }
-
- ///
- /// Perform an actual commit on the given transaction.
- ///
- /// The status representation of the transaction.
- ///
- ///
- /// An implementation does not need to check the rollback-only flag.
- ///
- ///
- ///
- /// In the case of system errors.
- ///
- protected override void DoCommit(DefaultTransactionStatus status)
- {
- HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;
- if (status.Debug)
- {
- log.Debug("Committing Hibernate transaction on Session [" +
- txObject.SessionHolder.Session + "]");
- }
- try
- {
- txObject.SessionHolder.Transaction.Commit();
- }
- // Note, unfortunate collision of namespaces/classname for NHibernate.TransactionException
- // and Spring.Data.NHibernate requires this wierd construct.
- catch (Exception ex)
- {
- Type nhibTxExceptiontype = TypeResolutionUtils.ResolveType("NHibernate.TransactionException, NHibernate");
- if (ex.GetType().Equals(nhibTxExceptiontype))
- {
- // assumably from commit call to the underlying ADO.NET connection
- throw new TransactionSystemException("Could not commit Hibernate transaction", ex);
- }
- HibernateException hibEx = ex as HibernateException;
- if (hibEx != null)
- {
- // assumably failed to flush changes to database
- throw ConvertHibernateAccessException(hibEx);
- }
- throw;
- }
- finally
- {
- DoTxScopeCommit(status);
- }
-
-
-
- }
-
- ///
- /// Does the tx scope commit.
- ///
- /// The status.
- protected void DoTxScopeCommit(DefaultTransactionStatus status)
- {
- TxScopeTransactionManager.PromotableTxScopeTransactionObject txObject =
- ((HibernateTransactionObject)status.Transaction).PromotableTxScopeTransactionObject;
- try
- {
- txObject.TxScopeAdapter.Complete();
- txObject.TxScopeAdapter.Dispose();
- }
- catch (TransactionAbortedException ex)
- {
- throw new UnexpectedRollbackException("Transaction unexpectedly rolled back (maybe due to a timeout)", ex);
- }
- catch (TransactionInDoubtException ex)
- {
- throw new HeuristicCompletionException(TransactionOutcomeState.Unknown, ex);
- }
- catch (Exception ex)
- {
- throw new TransactionSystemException("Failure on Transaction Scope Commit", ex);
- }
- }
-
- ///
- /// Perform an actual rollback on the given transaction.
- ///
- /// The status representation of the transaction.
- ///
- /// An implementation does not need to check the new transaction flag.
- ///
- ///
- /// In the case of system errors.
- ///
- protected override void DoRollback(DefaultTransactionStatus status)
- {
- HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;
-
- if (!txObject.NewSessionHolder)
- {
- // Clear all pending inserts/updates/deletes in the Session.
- // Necessary for pre-bound Sessions, to avoid inconsistent state.
- txObject.SessionHolder.Session.Clear();
- }
-
- DoTxScopeRollback(status);
- return;
-
-
- /* HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;
-
- if (status.Debug)
- {
- log.Debug("Rolling back Hibernate transaction on Session [" +
- txObject.SessionHolder.Session + "]");
- }
- try
- {
- if (txObject.SessionHolder.Session != null && txObject.SessionHolder.Transaction != null && !txObject.SessionHolder.Transaction.IsActive)
- {
- return;
- }
-
- IDbTransaction adoTx = GetIDbTransaction(txObject.SessionHolder.Transaction);
-
- if (adoTx != null && adoTx.Connection != null)
- {
- txObject.SessionHolder.Transaction.Rollback();
- }
- else
- {
- if (status.Debug)
- {
- log.Debug("Unable to RollBack Hibernate transaction; connection for Hibernate transaction on Session [" +
- txObject.SessionHolder.Session + "] was null");
- }
- }
-
- }
- catch (HibernateTransactionException ex)
- {
- throw new TransactionSystemException("Could not roll back Hibernate transaction", ex);
- }
- catch (HibernateException ex)
- {
- // Shouldn't really happen, as a rollback doesn't cause a flush.
- throw ConvertHibernateAccessException(ex);
- }
- finally
- {
- if (!txObject.NewSessionHolder)
- {
- // Clear all pending inserts/updates/deletes in the Session.
- // Necessary for pre-bound Sessions, to avoid inconsistent state.
- txObject.SessionHolder.Session.Clear();
- }
- DoTxScopeRollback(status);
- }*/
- }
-
- ///
- /// Does the tx scope rollback.
- ///
- /// The status.
- protected void DoTxScopeRollback(DefaultTransactionStatus status)
- {
- TxScopeTransactionManager.PromotableTxScopeTransactionObject txObject =
- ((HibernateTransactionObject)status.Transaction).PromotableTxScopeTransactionObject;
-
- try
- {
-
- txObject.TxScopeAdapter.Dispose();
- }
- catch (Exception e)
- {
- throw new Spring.Transaction.TransactionSystemException("Failure on Transaction Scope rollback.", e);
- }
- }
-
- ///
- /// Set the given transaction rollback-only. Only called on rollback
- /// if the current transaction takes part in an existing one.
- ///
- /// The status representation of the transaction.
- ///
- /// In the case of system errors.
- ///
- protected override void DoSetRollbackOnly(DefaultTransactionStatus status)
- {
- HibernateTransactionObject txObject = (HibernateTransactionObject)status.Transaction;
- if (status.Debug)
- {
- log.Debug("Setting Hibernate transaction on Session [" +
- txObject.SessionHolder.Session + "] rollback-only");
- }
- txObject.SetRollbackOnly();
-
- DoTxScopeSetRollbackOnly(status);
- }
-
- ///
- /// Does the tx scope set rollback only.
- ///
- /// The status.
- protected void DoTxScopeSetRollbackOnly(DefaultTransactionStatus status)
- {
- if (status.Debug)
- {
- log.Debug("Setting transaction rollback-only");
- }
- try
- {
- System.Transactions.Transaction.Current.Rollback();
- }
- catch (Exception ex)
- {
- throw new TransactionSystemException("Failure on System.Transactions.Transaction.Current.Rollback", ex);
- }
- }
-
-
- ///
- /// Gets the ADO.NET IDbTransaction object from the NHibernate ITransaction object.
- ///
- /// The hibernate transaction.
- /// The ADO.NET transaction. Null if could not get the transaction. Warning
- /// messages will be logged in that case.
- protected IDbTransaction GetIDbTransaction(ITransaction hibernateTx)
- {
- AdoTransaction hibernateAdoTx = hibernateTx as AdoTransaction;
-
- IDbTransaction adoTransaction = null;
- if (hibernateAdoTx != null)
- {
- try
- {
- FieldInfo fi = hibernateAdoTx.GetType().GetField("trans", BindingFlags.Instance | BindingFlags.NonPublic);
- adoTransaction = fi.GetValue(hibernateAdoTx) as IDbTransaction;
- }
- catch (Exception e)
- {
- log.Warn("Could not extract IDbTransaction from Hibernate AdoTransaction using field name trans.", e);
- }
- }
- else
- {
- log.Warn("Hibernate ITransaction not of expected type AdoTransaction. Could not extract IDbTransaction from Hibernate AdoTransaction.");
- }
- return adoTransaction;
- }
-
- ///
- /// Convert the given HibernateException to an appropriate exception from
- /// the Spring.Dao hierarchy. Can be overridden in subclasses.
- ///
- /// The HibernateException that occured.
- /// The corresponding DataAccessException instance
- protected virtual DataAccessException ConvertHibernateAccessException(HibernateException ex)
- {
- if (AdoExceptionTranslator != null && ex is ADOException)
- {
- return ConvertAdoAccessException((ADOException)ex, AdoExceptionTranslator);
- }
- else if (ex is ADOException)
- {
- return ConvertAdoAccessException((ADOException)ex, DefaultAdoExceptionTranslator);
- }
- return SessionFactoryUtils.ConvertHibernateAccessException(ex);
- }
-
- ///
- /// Convert the given ADOException to an appropriate exception from the
- /// the Spring.Dao hierarchy. Can be overridden in subclasses.
- ///
- /// The ADOException that occured, wrapping the underlying
- /// ADO.NET thrown exception.
- /// The translator to convert hibernate ADOExceptions.
- ///
- /// The corresponding DataAccessException instance
- ///
- protected virtual DataAccessException ConvertAdoAccessException(ADOException ex, IAdoExceptionTranslator translator)
- {
- return translator.Translate("Hibernate flushing: " + ex.Message, null, ex.InnerException);
- }
-
- ///
- /// Cleanup resources after transaction completion.
- ///
- /// Transaction object returned by
- /// .
- ///
- ///
- /// This implemenation unbinds the SessionFactory and
- /// DbProvider from thread local storage and closes the
- /// ISession.
- ///
- ///
- /// Called after
- /// and
- ///
- /// execution on any outcome.
- ///
- ///
- /// Should not throw any exceptions but just issue warnings on errors.
- ///
- ///
- protected override void DoCleanupAfterCompletion(object transaction)
- {
- HibernateTransactionObject txObject = (HibernateTransactionObject)transaction;
-
- // Remove the session holder from the thread.
- if (txObject.NewSessionHolder)
- {
- TransactionSynchronizationManager.UnbindResource(SessionFactory);
- }
- // Remove the ADO.NET connection holder from the thread, if exposed.
- if (DbProvider != null)
- {
- TransactionSynchronizationManager.UnbindResource(DbProvider);
- }
- /*
- try
- {
- //TODO investigate isolation level settings...
- //IDbConnection con = txObject.SessionHolder.Session.Connection;
- //AdoUtils.ResetConnectionAfterTransaction(con, txObject.PreviousIsolationLevel);
- }
- catch (HibernateException ex)
- {
- log.Info("Could not access ADO.NET IDbConnection of Hibernate Session", ex);
- }
- */
- ISession session = txObject.SessionHolder.Session;
- if (txObject.NewSessionHolder)
- {
- if (log.IsDebugEnabled)
- {
- log.Debug("Closing Hibernate Session [" + session + "] after transaction");
- }
- // SessionFactoryUtils.CloseSessionOrRegisterDeferredClose(session, SessionFactory);
- // NOTE: The above line has to be called via reflection since it is an internal method
- SessionFactoryUtils_CloseSessionOrRegisterDeferredClose_Method.Invoke(null, BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.NonPublic, null, new object[] { session, SessionFactory }, null);
- }
- else
- {
- if (log.IsDebugEnabled)
- {
- log.Debug("Not closing pre-bound Hibernate Session [" + session + "] after transaction");
- }
- if (txObject.SessionHolder.AssignedPreviousFlushMode)
- {
- session.FlushMode = txObject.SessionHolder.PreviousFlushMode;
- }
- }
- txObject.SessionHolder.Clear();
-
-
- }
-
- private class HibernateTransactionObject : AdoTransactionObjectSupport
- {
-
- private SessionHolder sessionHolder;
-
- private bool newSessionHolder;
-
- private TxScopeTransactionManager.PromotableTxScopeTransactionObject promotableTxScopeTransactionObject;
-
-
- public void SetSessionHolder(SessionHolder sessionHolder, bool newSessionHolder)
- {
- this.sessionHolder = sessionHolder;
- this.newSessionHolder = newSessionHolder;
- }
-
- public TxScopeTransactionManager.PromotableTxScopeTransactionObject PromotableTxScopeTransactionObject
- {
- get { return promotableTxScopeTransactionObject; }
- set { this.promotableTxScopeTransactionObject = value; }
- }
-
- public SessionHolder SessionHolder
- {
- get
- {
- return sessionHolder;
- }
- }
-
- public bool NewSessionHolder
- {
- get
- {
- return newSessionHolder;
- }
- }
-
- public bool HasTransaction()
- {
- return (this.sessionHolder != null && this.sessionHolder.Transaction != null);
- }
-
- public void SetRollbackOnly()
- {
- if (SessionHolder != null)
- {
- SessionHolder.RollbackOnly = true;
- }
- if (ConnectionHolder != null)
- {
- ConnectionHolder.RollbackOnly = true;
- }
- }
-
- ///
- /// Return whether the transaction is internally marked as rollback-only.
- ///
- ///
- /// True of the transaction is marked as rollback-only.
- public override bool RollbackOnly
- {
- get
- {
- return ((SessionHolder != null && SessionHolder.RollbackOnly) ||
- (ConnectionHolder != null && ConnectionHolder.RollbackOnly));
- }
- }
- }
-
- private class SuspendedResourcesHolder
- {
-
- private readonly SessionHolder sessionHolder;
-
- private readonly ConnectionHolder connectionHolder;
-
- public SuspendedResourcesHolder(SessionHolder sessionHolder, ConnectionHolder conHolder)
- {
- this.sessionHolder = sessionHolder;
- this.connectionHolder = conHolder;
- }
-
- public SessionHolder SessionHolder
- {
- get
- {
- return sessionHolder;
- }
-
- }
-
- public ConnectionHolder ConnectionHolder
- {
- get
- {
- return connectionHolder;
- }
-
- }
- }
-
- ///
- /// Invoked by an
- /// after it has injected all of an object's dependencies.
- ///
- ///
- ///
- /// This method allows the object instance to perform the kind of
- /// initialization only possible when all of it's dependencies have
- /// been injected (set), and to throw an appropriate exception in the
- /// event of misconfiguration.
- ///
- ///
- /// Please do consult the class level documentation for the
- /// interface for a
- /// description of exactly when this method is invoked. In
- /// particular, it is worth noting that the
- ///
- /// and
- /// callbacks will have been invoked prior to this method being
- /// called.
- ///
- ///
- ///
- /// In the event of misconfiguration (such as the failure to set a
- /// required property) or if initialization fails.
- ///
- public void AfterPropertiesSet()
- {
- if (SessionFactory == null)
- {
- throw new ArgumentException("sessionFactory is required");
- }
- if (this.entityInterceptor is string && this.objectFactory == null)
- {
- throw new ArgumentException("objectFactory is required for entityInterceptorBeanName");
- }
-
- // Try to derive a DbProvider given the SessionFactory.
- if (this.autodetectDbProvider && DbProvider == null)
- {
- IDbProvider sfDbProvider = SessionFactoryUtils.GetDbProvider(SessionFactory);
- if (sfDbProvider != null)
- {
- // Use the SessionFactory's DataSource for exposing transactions to ADO.NET code.
- if (log.IsInfoEnabled)
- {
- log.Info("Derived DbProvider [" + sfDbProvider.DbMetadata.ProductName +
- "] of Hibernate SessionFactory for HibernateTransactionManager");
- }
- DbProvider = sfDbProvider;
- }
- else
- {
- log.Info("Could not auto detect DbProvider from SessionFactory configuration");
- }
-
- }
- }
-
- private static string WriteTransactionInformation(System.Transactions.Transaction tx)
- {
- if (tx == null)
- {
- return "NULL";
- }
-
- string isoLevel = System.Transactions.Transaction.Current.IsolationLevel.ToString();
- TransactionInformation txInfo = System.Transactions.Transaction.Current.TransactionInformation;
- return string.Format("{{LocalId = {0}, DistributedId = {1}, Status = {2}, IsolationLevel = {3}, CreationTime = {4}}}", txInfo.LocalIdentifier, txInfo.DistributedIdentifier, txInfo.Status, isoLevel, txInfo.CreationTime.ToString("o"));
- }
-
- }
-}
diff --git a/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml b/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml
deleted file mode 100644
index 5657013e..00000000
--- a/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests.csproj b/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests.csproj
index 9b6c8909..2231a6d1 100644
--- a/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests.csproj
+++ b/test/Spring/Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests.csproj
@@ -56,8 +56,6 @@
-
-
@@ -97,8 +95,6 @@
-
-
diff --git a/test/Spring/Spring.SessionFactoryImplError.Tests/TestUsingCustomHibernateTxScopeTransactionManager.cs b/test/Spring/Spring.SessionFactoryImplError.Tests/TestUsingCustomHibernateTxScopeTransactionManager.cs
deleted file mode 100644
index 9766825e..00000000
--- a/test/Spring/Spring.SessionFactoryImplError.Tests/TestUsingCustomHibernateTxScopeTransactionManager.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-using NUnit.Framework;
-using Spring.Data.NHibernate.Generic;
-using Spring.Testing.NUnit;
-
-namespace Spring.SessionFactoryImplError.Tests
-{
- [TestFixture]
- public class TestUsingCustomHibernateTxScopeTransactionManager : AbstractTransactionalSpringContextTests
- {
- #region DI
-
- public HibernateTemplate HibernateTemplate { get; set; }
- public IService1 Service1 { get; set; }
- public IService2 Service2 { get; set; }
-
- #endregion
-
- protected override string[] ConfigLocations
- {
- get
- {
- return new[]
- {
- "config://spring/objects",
- "assembly://Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests/Spring.Configuration.xml",
- "assembly://Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests/Spring.NHibernate.xml",
- "assembly://Spring.SessionFactoryImplError.Tests/Spring.SessionFactoryImplError.Tests/Spring.CustomHibernateTxScopeTransactionManager.xml"
- };
- }
- }
-
- [Test(Description = "This is failing test case in my unit test with original NH TX Scope Manager, but not Custom TX Scope Manager, Not Supported -> Not Supported")]
- public void TestSuspendTransactionOnNotSupported()
- {
- Service1.ServiceMethodWithNotSupported1();
- }
-
- [Test(Description = "This is also failing with NH TX Scope manager, but nto with Custom TX Scope Manager, Not Supported -> Requires New")]
- public void TestSuspendTransactionOnNotSupportedWithNestedRequiresNew()
- {
- Service2.ServiceMethodWithNotSupported();
- }
-
- [Test(Description = "This is failing test case in my unit test with Custom TX Scope Manager (this is the original bug reported), Not Supported -> Not Supported -> Required")]
- public void TestSuspendTransactionOnNotSupportedWithNestedRequired()
- {
- Service1.ServiceMethodWithNotSupported3();
- }
- }
-}