/// <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);
}
}