SPRNET-1410 , SPRNET-1438
- properly handle zombied Transaction (Tx without a valid IDbConnection) on Rollback - mod to underlying AbstractPlatformTransactionManager to set default Transaction Sync to TransactionSynchronization.Never
This commit is contained in:
@@ -1,32 +0,0 @@
|
||||
<Configuration>
|
||||
<SettingsComponent>
|
||||
<string />
|
||||
<integer />
|
||||
<boolean>
|
||||
<setting name="SolutionAnalysisEnabled">False</setting>
|
||||
</boolean>
|
||||
</SettingsComponent>
|
||||
<NAntValidationSettings>
|
||||
<NAntPath value="" />
|
||||
</NAntValidationSettings>
|
||||
<CompletionStatisticsManager>
|
||||
<ItemStatistics item="Default">
|
||||
<Item value="string" priority="2" />
|
||||
<Item value="private" priority="1" />
|
||||
<Item value="IMessageService" priority="0" />
|
||||
<Item value="return" priority="0" />
|
||||
</ItemStatistics>
|
||||
</CompletionStatisticsManager>
|
||||
<RecentFiles>
|
||||
<RecentFiles>
|
||||
<File id="94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048/f:App.Tests.dll.config" caret="747" fromTop="21" />
|
||||
<File id="94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048/f:system-test-config.xml" caret="347" fromTop="10" />
|
||||
</RecentFiles>
|
||||
<RecentEdits>
|
||||
<File id="94E4E1B4-D424-4EB9-BF34-2EE8CC3D7048/f:system-test-config.xml" caret="360" fromTop="10" />
|
||||
</RecentEdits>
|
||||
</RecentFiles>
|
||||
<UnitTestRunner>
|
||||
<Providers />
|
||||
</UnitTestRunner>
|
||||
</Configuration>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -260,7 +260,7 @@ namespace Spring.Data.NHibernate
|
||||
// Spring transaction management is active ->
|
||||
// register pre-bound Session with it for transactional flushing.
|
||||
session = sessionHolder.ValidatedSession;
|
||||
if (!sessionHolder.SynchronizedWithTransaction)
|
||||
if (session != null && !sessionHolder.SynchronizedWithTransaction)
|
||||
{
|
||||
log.Debug("Registering Spring transaction synchronization for existing Hibernate Session");
|
||||
TransactionSynchronizationManager.RegisterSynchronization(
|
||||
|
||||
@@ -716,6 +716,20 @@ namespace Spring.Data.NHibernate
|
||||
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 [" +
|
||||
@@ -723,6 +737,11 @@ namespace Spring.Data.NHibernate
|
||||
}
|
||||
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)
|
||||
@@ -737,7 +756,7 @@ namespace Spring.Data.NHibernate
|
||||
txObject.SessionHolder.Session + "] was null");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (HibernateTransactionException ex)
|
||||
{
|
||||
@@ -757,7 +776,7 @@ namespace Spring.Data.NHibernate
|
||||
txObject.SessionHolder.Session.Clear();
|
||||
}
|
||||
DoTxScopeRollback(status);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,288 +1,288 @@
|
||||
#if NET_2_0
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Transactions;
|
||||
using Spring.Data.Support;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Transaction;
|
||||
using Spring.Transaction.Support;
|
||||
|
||||
namespace Spring.Data.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// TransactionManager that uses TransactionScope provided by System.Transactions.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class TxScopeTransactionManager : AbstractPlatformTransactionManager, IInitializingObject
|
||||
{
|
||||
private readonly ITransactionScopeAdapter txAdapter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TxScopeTransactionManager"/> class.
|
||||
/// </summary>
|
||||
public TxScopeTransactionManager()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TxScopeTransactionManager"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>This is indented only for unit testing purposes and should not be
|
||||
/// called by production application code.</remarks>
|
||||
/// <param name="txAdapter">The tx adapter.</param>
|
||||
public TxScopeTransactionManager(ITransactionScopeAdapter txAdapter)
|
||||
{
|
||||
this.txAdapter = txAdapter;
|
||||
}
|
||||
|
||||
#region IInitializingObject Members
|
||||
|
||||
/// <summary>
|
||||
/// No-op initialization
|
||||
/// </summary>
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
// placeholder for more advanced configurations.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override object DoGetTransaction()
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject = new PromotableTxScopeTransactionObject();
|
||||
|
||||
if (txAdapter != null)
|
||||
{
|
||||
txObject.TxScopeAdapter = txAdapter;
|
||||
}
|
||||
return txObject;
|
||||
}
|
||||
|
||||
protected override bool IsExistingTransaction(object transaction)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)transaction;
|
||||
return txObject.TxScopeAdapter.IsExistingTransaction;
|
||||
}
|
||||
|
||||
protected override void DoBegin(object transaction, Spring.Transaction.ITransactionDefinition definition)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)transaction;
|
||||
try
|
||||
{
|
||||
DoTxScopeBegin(txObject, definition);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CannotCreateTransactionException("Transaction Scope failure on begin", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected override object DoSuspend(object transaction)
|
||||
{
|
||||
// Passing the current TxScopeAdapter as the 'suspended resource', even though it is not used just to avoid passing null
|
||||
// TxScopeTransactionManager is not binding any resources to the local thread, instead delegating to
|
||||
// System.Transactions to handle thread local resources.
|
||||
PromotableTxScopeTransactionObject txMgrStateObject = (PromotableTxScopeTransactionObject) transaction;
|
||||
return txMgrStateObject.TxScopeAdapter;
|
||||
}
|
||||
|
||||
protected override void DoResume(object transaction, object suspendedResources)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void DoCommit(DefaultTransactionStatus status)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)status.Transaction;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DoRollback(DefaultTransactionStatus status)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)status.Transaction;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
txObject.TxScopeAdapter.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Spring.Transaction.TransactionSystemException("Failure on Transaction Scope rollback.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void DoSetRollbackOnly(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);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ShouldCommitOnGlobalRollbackOnly
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
private void DoTxScopeBegin(PromotableTxScopeTransactionObject txObject,
|
||||
Spring.Transaction.ITransactionDefinition definition)
|
||||
{
|
||||
|
||||
TransactionScopeOption txScopeOption = CreateTransactionScopeOptions(definition);
|
||||
TransactionOptions txOptions = CreateTransactionOptions(definition);
|
||||
txObject.TxScopeAdapter.CreateTransactionScope(txScopeOption, txOptions, definition.EnterpriseServicesInteropOption);
|
||||
|
||||
}
|
||||
|
||||
private static TransactionOptions CreateTransactionOptions(ITransactionDefinition definition)
|
||||
{
|
||||
TransactionOptions txOptions = new TransactionOptions();
|
||||
switch (definition.TransactionIsolationLevel )
|
||||
{
|
||||
case System.Data.IsolationLevel.Chaos:
|
||||
txOptions.IsolationLevel = IsolationLevel.Chaos;
|
||||
break;
|
||||
case System.Data.IsolationLevel.ReadCommitted:
|
||||
txOptions.IsolationLevel = IsolationLevel.ReadCommitted;
|
||||
break;
|
||||
case System.Data.IsolationLevel.ReadUncommitted:
|
||||
txOptions.IsolationLevel = IsolationLevel.ReadUncommitted;
|
||||
break;
|
||||
case System.Data.IsolationLevel.RepeatableRead:
|
||||
txOptions.IsolationLevel = IsolationLevel.RepeatableRead;
|
||||
break;
|
||||
case System.Data.IsolationLevel.Serializable:
|
||||
txOptions.IsolationLevel = IsolationLevel.Serializable;
|
||||
break;
|
||||
case System.Data.IsolationLevel.Snapshot:
|
||||
txOptions.IsolationLevel = IsolationLevel.Snapshot;
|
||||
break;
|
||||
case System.Data.IsolationLevel.Unspecified:
|
||||
txOptions.IsolationLevel = IsolationLevel.Unspecified;
|
||||
break;
|
||||
}
|
||||
|
||||
if (definition.TransactionTimeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
|
||||
{
|
||||
txOptions.Timeout = new TimeSpan(0, 0, definition.TransactionTimeout);
|
||||
}
|
||||
return txOptions;
|
||||
}
|
||||
|
||||
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)
|
||||
#if NET_2_0
|
||||
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Transactions;
|
||||
using Spring.Data.Support;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Transaction;
|
||||
using Spring.Transaction.Support;
|
||||
|
||||
namespace Spring.Data.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// TransactionManager that uses TransactionScope provided by System.Transactions.
|
||||
/// </summary>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public class TxScopeTransactionManager : AbstractPlatformTransactionManager, IInitializingObject
|
||||
{
|
||||
private readonly ITransactionScopeAdapter txAdapter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TxScopeTransactionManager"/> class.
|
||||
/// </summary>
|
||||
public TxScopeTransactionManager()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TxScopeTransactionManager"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>This is indented only for unit testing purposes and should not be
|
||||
/// called by production application code.</remarks>
|
||||
/// <param name="txAdapter">The tx adapter.</param>
|
||||
public TxScopeTransactionManager(ITransactionScopeAdapter txAdapter)
|
||||
{
|
||||
this.txAdapter = txAdapter;
|
||||
}
|
||||
|
||||
#region IInitializingObject Members
|
||||
|
||||
/// <summary>
|
||||
/// No-op initialization
|
||||
/// </summary>
|
||||
public void AfterPropertiesSet()
|
||||
{
|
||||
// placeholder for more advanced configurations.
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override object DoGetTransaction()
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject = new PromotableTxScopeTransactionObject();
|
||||
|
||||
if (txAdapter != null)
|
||||
{
|
||||
txObject.TxScopeAdapter = txAdapter;
|
||||
}
|
||||
return txObject;
|
||||
}
|
||||
|
||||
protected override bool IsExistingTransaction(object transaction)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)transaction;
|
||||
return txObject.TxScopeAdapter.IsExistingTransaction;
|
||||
}
|
||||
|
||||
protected override void DoBegin(object transaction, Spring.Transaction.ITransactionDefinition definition)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)transaction;
|
||||
try
|
||||
{
|
||||
DoTxScopeBegin(txObject, definition);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new CannotCreateTransactionException("Transaction Scope failure on begin", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected override object DoSuspend(object transaction)
|
||||
{
|
||||
// Passing the current TxScopeAdapter as the 'suspended resource', even though it is not used just to avoid passing null
|
||||
// TxScopeTransactionManager is not binding any resources to the local thread, instead delegating to
|
||||
// System.Transactions to handle thread local resources.
|
||||
PromotableTxScopeTransactionObject txMgrStateObject = (PromotableTxScopeTransactionObject) transaction;
|
||||
return txMgrStateObject.TxScopeAdapter;
|
||||
}
|
||||
|
||||
protected override void DoResume(object transaction, object suspendedResources)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void DoCommit(DefaultTransactionStatus status)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)status.Transaction;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DoRollback(DefaultTransactionStatus status)
|
||||
{
|
||||
PromotableTxScopeTransactionObject txObject =
|
||||
(PromotableTxScopeTransactionObject)status.Transaction;
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
txObject.TxScopeAdapter.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new Spring.Transaction.TransactionSystemException("Failure on Transaction Scope rollback.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void DoSetRollbackOnly(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);
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ShouldCommitOnGlobalRollbackOnly
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
private void DoTxScopeBegin(PromotableTxScopeTransactionObject txObject,
|
||||
Spring.Transaction.ITransactionDefinition definition)
|
||||
{
|
||||
|
||||
TransactionScopeOption txScopeOption = CreateTransactionScopeOptions(definition);
|
||||
TransactionOptions txOptions = CreateTransactionOptions(definition);
|
||||
txObject.TxScopeAdapter.CreateTransactionScope(txScopeOption, txOptions, definition.EnterpriseServicesInteropOption);
|
||||
|
||||
}
|
||||
|
||||
private static TransactionOptions CreateTransactionOptions(ITransactionDefinition definition)
|
||||
{
|
||||
TransactionOptions txOptions = new TransactionOptions();
|
||||
switch (definition.TransactionIsolationLevel )
|
||||
{
|
||||
case System.Data.IsolationLevel.Chaos:
|
||||
txOptions.IsolationLevel = IsolationLevel.Chaos;
|
||||
break;
|
||||
case System.Data.IsolationLevel.ReadCommitted:
|
||||
txOptions.IsolationLevel = IsolationLevel.ReadCommitted;
|
||||
break;
|
||||
case System.Data.IsolationLevel.ReadUncommitted:
|
||||
txOptions.IsolationLevel = IsolationLevel.ReadUncommitted;
|
||||
break;
|
||||
case System.Data.IsolationLevel.RepeatableRead:
|
||||
txOptions.IsolationLevel = IsolationLevel.RepeatableRead;
|
||||
break;
|
||||
case System.Data.IsolationLevel.Serializable:
|
||||
txOptions.IsolationLevel = IsolationLevel.Serializable;
|
||||
break;
|
||||
case System.Data.IsolationLevel.Snapshot:
|
||||
txOptions.IsolationLevel = IsolationLevel.Snapshot;
|
||||
break;
|
||||
case System.Data.IsolationLevel.Unspecified:
|
||||
txOptions.IsolationLevel = IsolationLevel.Unspecified;
|
||||
break;
|
||||
}
|
||||
|
||||
if (definition.TransactionTimeout != DefaultTransactionDefinition.TIMEOUT_DEFAULT)
|
||||
{
|
||||
txOptions.Timeout = new TimeSpan(0, 0, definition.TransactionTimeout);
|
||||
}
|
||||
return txOptions;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The transaction resource object that encapsulates the state and functionality
|
||||
/// contained in TransactionScope and Transaction.Current via the ITransactionScopeAdapter
|
||||
/// property.
|
||||
/// </summary>
|
||||
public class PromotableTxScopeTransactionObject : ISmartTransactionObject
|
||||
{
|
||||
private ITransactionScopeAdapter txScopeAdapter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PromotableTxScopeTransactionObject"/> class.
|
||||
/// Will create an instance of <see cref="DefaultTransactionScopeAdapter"/>.
|
||||
/// </summary>
|
||||
public PromotableTxScopeTransactionObject()
|
||||
{
|
||||
txScopeAdapter = new DefaultTransactionScopeAdapter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transaction scope adapter.
|
||||
/// </summary>
|
||||
/// <value>The transaction scope adapter.</value>
|
||||
public ITransactionScopeAdapter TxScopeAdapter
|
||||
{
|
||||
get { return txScopeAdapter; }
|
||||
set { txScopeAdapter = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return whether the transaction is internally marked as rollback-only.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <returns>True of the transaction is marked as rollback-only.</returns>
|
||||
public bool RollbackOnly
|
||||
{
|
||||
get {
|
||||
return txScopeAdapter.RollbackOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Spring.Transaction.TransactionSystemException("Transaction Propagation Behavior" +
|
||||
definition.PropagationBehavior +
|
||||
" not supported by TransactionScope. Use Required or RequiredNew");
|
||||
}
|
||||
return txScopeOption;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The transaction resource object that encapsulates the state and functionality
|
||||
/// contained in TransactionScope and Transaction.Current via the ITransactionScopeAdapter
|
||||
/// property.
|
||||
/// </summary>
|
||||
public class PromotableTxScopeTransactionObject : ISmartTransactionObject
|
||||
{
|
||||
private ITransactionScopeAdapter txScopeAdapter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PromotableTxScopeTransactionObject"/> class.
|
||||
/// Will create an instance of <see cref="DefaultTransactionScopeAdapter"/>.
|
||||
/// </summary>
|
||||
public PromotableTxScopeTransactionObject()
|
||||
{
|
||||
txScopeAdapter = new DefaultTransactionScopeAdapter();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transaction scope adapter.
|
||||
/// </summary>
|
||||
/// <value>The transaction scope adapter.</value>
|
||||
public ITransactionScopeAdapter TxScopeAdapter
|
||||
{
|
||||
get { return txScopeAdapter; }
|
||||
set { txScopeAdapter = value; }
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return whether the transaction is internally marked as rollback-only.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
/// <returns>True of the transaction is marked as rollback-only.</returns>
|
||||
public bool RollbackOnly
|
||||
{
|
||||
get {
|
||||
return txScopeAdapter.RollbackOnly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,492 +1,492 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Spring.Core;
|
||||
using Spring.Threading;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Transaction.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal class that manages resources and transaction synchronizations per thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Supports one resource per key without overwriting, i.e. a resource needs to
|
||||
/// be removed before a new one can be set for the same key.
|
||||
/// Supports a list of transaction synchronizations if synchronization is active.
|
||||
/// <p>
|
||||
/// Resource management code should check for thread-bound resources via GetResource().
|
||||
/// It is normally not supposed
|
||||
/// to bind resources to threads, as this is the responsiblity of transaction managers.
|
||||
/// A further option is to lazily bind on first use if transaction synchronization
|
||||
/// is active, for performing transactions that span an arbitrary number of resources.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Transaction synchronization must be activated and deactivated by a transaction
|
||||
/// manager via
|
||||
/// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager.InitSynchronization">InitSynchronization</see>
|
||||
/// and
|
||||
/// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager.ClearSynchronization">ClearSynchronization</see>.
|
||||
/// This is automatically supported by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager"/>.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Resource management code should only register synchronizations when this
|
||||
/// manager is active, and perform resource cleanup immediately else.
|
||||
/// If transaction synchronization isn't active, there is either no current
|
||||
/// transaction, or the transaction manager doesn't support synchronizations.
|
||||
/// </p>
|
||||
/// Note that this class uses following naming convention for the
|
||||
/// named 'data slots' for storage of thread local data, 'Spring.Transaction:Name'
|
||||
/// where Name is either
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Griffin Caprio (.NET)</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public sealed class TransactionSynchronizationManager
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof (TransactionSynchronizationManager));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private static readonly string syncsDataSlotName = "Spring.Transactions:syncList";
|
||||
|
||||
private static readonly string resourcesDataSlotName = "Spring.Transactions:resources";
|
||||
|
||||
private static readonly string currentTxReadOnlyDataSlotName = "Spring.Transactions:currentTxReadOnly";
|
||||
|
||||
private static readonly string currentTxNameDataSlotName = "Spring.Transactions:currentTxName";
|
||||
|
||||
private static readonly string currentTxIsolationLevelDataSlotName = "Spring.Transactions:currentTxIsolationLevel";
|
||||
|
||||
private static readonly string actualTxActiveDataSlotName = "Spring.Transactions:actualTxActive";
|
||||
|
||||
private static IComparer syncComparer = new OrderComparator();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Management of transaction-associated resource handles
|
||||
/// <summary>
|
||||
/// Return all resources that are bound to the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>Main for debugging purposes. Resource manager should always
|
||||
/// invoke HasResource for a specific resource key that they are interested in.
|
||||
/// </remarks>
|
||||
/// <returns>IDictionary with resource keys and resource objects or empty
|
||||
/// dictionary if none is bound.</returns>
|
||||
public static IDictionary ResourceDictionary
|
||||
{
|
||||
get
|
||||
{
|
||||
IDictionary resources = LogicalThreadContext.GetData(resourcesDataSlotName) as IDictionary;
|
||||
if (resources != null)
|
||||
{
|
||||
//TODO add readonly wrapper in Spring.Collections.
|
||||
return resources;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Hashtable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if there is a resource for the given key bound to the current thread.
|
||||
/// </summary>
|
||||
/// <param name="key">key to check</param>
|
||||
/// <returns>if there is a value bound to the current thread</returns>
|
||||
public static bool HasResource(Object key)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(key, "Key must not be null");
|
||||
return ResourceDictionary.Contains(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a resource for the given key that is bound to the current thread.
|
||||
/// </summary>
|
||||
/// <param name="key">key to check</param>
|
||||
/// <returns>a value bound to the current thread, or null if none.</returns>
|
||||
public static object GetResource(Object key)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(key, "Key must not be null");
|
||||
IDictionary resources = LogicalThreadContext.GetData(resourcesDataSlotName) as IDictionary;
|
||||
if (resources == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//Check for contains since indexer returning null behavior changes in 2.0
|
||||
if (!resources.Contains(key))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
object val = resources[key];
|
||||
|
||||
if (val != null && LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Retrieved value [" + Describe(val) + "] for key [" + Describe(key) + "] bound to thread [" +
|
||||
SystemUtils.ThreadId + "]");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bind the given resource for teh given key to the current thread
|
||||
/// </summary>
|
||||
/// <param name="key">key to bind the value to</param>
|
||||
/// <param name="value">value to bind</param>
|
||||
public static void BindResource(Object key, Object value)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(key, "Key value for thread local storage of transactional resources must not be null");
|
||||
AssertUtils.ArgumentNotNull(value, "Transactional resource to bind to thread local storage must not be null" );
|
||||
|
||||
IDictionary resources = LogicalThreadContext.GetData(resourcesDataSlotName) as IDictionary;
|
||||
//Set thread local resource storage if not found
|
||||
if (resources == null)
|
||||
{
|
||||
resources = new Hashtable();
|
||||
LogicalThreadContext.SetData(resourcesDataSlotName, resources);
|
||||
}
|
||||
if (resources.Contains(key))
|
||||
{
|
||||
throw new InvalidOperationException("Already value [" + resources[key] + "] for key [" + key +
|
||||
"] bound to thread [" + SystemUtils.ThreadId + "]");
|
||||
}
|
||||
resources.Add(key, value);
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Bound value [" + Describe(value) + "] for key [" + Describe(key) + "] to thread [" +
|
||||
SystemUtils.ThreadId + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Unbind a resource for the given key from the current thread
|
||||
/// </summary>
|
||||
/// <param name="key">key to check</param>
|
||||
/// <returns>the previously bound value</returns>
|
||||
/// <exception cref="InvalidOperationException">if there is no value bound to the thread</exception>
|
||||
public static object UnbindResource(Object key)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(key, "Key must not be null");
|
||||
|
||||
IDictionary resources = LogicalThreadContext.GetData(resourcesDataSlotName) as IDictionary;
|
||||
if (resources == null || !resources.Contains(key))
|
||||
{
|
||||
throw new InvalidOperationException("No value for key [" + key + "] bound to thread [" +
|
||||
SystemUtils.ThreadId + "]");
|
||||
}
|
||||
Object val = resources[key];
|
||||
resources.Remove(key);
|
||||
if (resources.Count == 0)
|
||||
{
|
||||
LogicalThreadContext.FreeNamedDataSlot(resourcesDataSlotName);
|
||||
}
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Removed value [" + Describe(val) + "] for key [" + Describe(key) + "] from thread [" +
|
||||
SystemUtils.ThreadId + "]");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Activate transaction synchronization for the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Called by transaction manager at the beginning of a transaction.
|
||||
/// </remarks>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If synchronization is already active.
|
||||
/// </exception>
|
||||
public static void InitSynchronization()
|
||||
{
|
||||
if ( SynchronizationActive )
|
||||
{
|
||||
throw new InvalidOperationException( "Cannot activate transaction synchronization - already active" );
|
||||
}
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Initializing transaction synchronization");
|
||||
}
|
||||
ArrayList syncs = new ArrayList();
|
||||
LogicalThreadContext.SetData(syncsDataSlotName, syncs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivate transaction synchronization for the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Called by transaction manager on transaction cleanup.
|
||||
/// </remarks>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If synchronization is not active.
|
||||
/// </exception>
|
||||
public static void ClearSynchronization()
|
||||
{
|
||||
if ( !SynchronizationActive )
|
||||
{
|
||||
throw new InvalidOperationException( "Cannot deactivate transaction synchronization - not active" );
|
||||
}
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Clearing transaction synchronization");
|
||||
}
|
||||
LogicalThreadContext.FreeNamedDataSlot(syncsDataSlotName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the entire transaction synchronization state for the current thread, registered
|
||||
/// synchronizations as well as the various transaction characteristics.
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
ClearSynchronization();
|
||||
CurrentTransactionName = null;
|
||||
CurrentTransactionReadOnly = false;
|
||||
CurrentTransactionIsolationLevel = IsolationLevel.Unspecified;
|
||||
ActualTransactionActive = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a new transaction synchronization for the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Typically called by resource management code.
|
||||
/// </remarks>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If synchronization is not active.
|
||||
/// </exception>
|
||||
public static void RegisterSynchronization( ITransactionSynchronization synchronization )
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(synchronization, "TransactionSynchronization must not be null");
|
||||
if ( !SynchronizationActive )
|
||||
{
|
||||
throw new InvalidOperationException( "Transaction synchronization is not active" );
|
||||
}
|
||||
ArrayList syncs = LogicalThreadContext.GetData(syncsDataSlotName) as ArrayList;
|
||||
if (syncs != null)
|
||||
{
|
||||
object root = syncs.SyncRoot;
|
||||
lock (root)
|
||||
{
|
||||
syncs.Add(synchronization);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string Describe(object obj)
|
||||
{
|
||||
return obj == null ? "" : obj + "@" + obj.GetHashCode().ToString("X");
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Return an unmodifiable list of all registered synchronizations
|
||||
/// for the current thread.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A list of <see cref="Spring.Transaction.Support.ITransactionSynchronization"/>
|
||||
/// instances.
|
||||
/// </returns>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If synchronization is not active.
|
||||
/// </exception>
|
||||
public static IList Synchronizations
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( ! SynchronizationActive )
|
||||
{
|
||||
throw new InvalidOperationException( "Transaction synchronization is not active" );
|
||||
}
|
||||
ArrayList syncs = LogicalThreadContext.GetData(syncsDataSlotName) as ArrayList;
|
||||
if (syncs != null)
|
||||
{
|
||||
// Sort lazily here, not in registerSynchronization.
|
||||
object root = syncs.SyncRoot;
|
||||
lock (root)
|
||||
{
|
||||
// #SPRNET-1160, tx Ben Rowlands
|
||||
CollectionUtils.StableSortInPlace(syncs, syncComparer);
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Data;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Spring.Core;
|
||||
using Spring.Threading;
|
||||
using Spring.Util;
|
||||
|
||||
namespace Spring.Transaction.Support
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal class that manages resources and transaction synchronizations per thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Supports one resource per key without overwriting, i.e. a resource needs to
|
||||
/// be removed before a new one can be set for the same key.
|
||||
/// Supports a list of transaction synchronizations if synchronization is active.
|
||||
/// <p>
|
||||
/// Resource management code should check for thread-bound resources via GetResource().
|
||||
/// It is normally not supposed
|
||||
/// to bind resources to threads, as this is the responsiblity of transaction managers.
|
||||
/// A further option is to lazily bind on first use if transaction synchronization
|
||||
/// is active, for performing transactions that span an arbitrary number of resources.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Transaction synchronization must be activated and deactivated by a transaction
|
||||
/// manager via
|
||||
/// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager.InitSynchronization">InitSynchronization</see>
|
||||
/// and
|
||||
/// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager.ClearSynchronization">ClearSynchronization</see>.
|
||||
/// This is automatically supported by
|
||||
/// <see cref="Spring.Transaction.Support.AbstractPlatformTransactionManager"/>.
|
||||
/// </p>
|
||||
/// <p>
|
||||
/// Resource management code should only register synchronizations when this
|
||||
/// manager is active, and perform resource cleanup immediately else.
|
||||
/// If transaction synchronization isn't active, there is either no current
|
||||
/// transaction, or the transaction manager doesn't support synchronizations.
|
||||
/// </p>
|
||||
/// Note that this class uses following naming convention for the
|
||||
/// named 'data slots' for storage of thread local data, 'Spring.Transaction:Name'
|
||||
/// where Name is either
|
||||
/// </remarks>
|
||||
/// <author>Juergen Hoeller</author>
|
||||
/// <author>Griffin Caprio (.NET)</author>
|
||||
/// <author>Mark Pollack (.NET)</author>
|
||||
public sealed class TransactionSynchronizationManager
|
||||
{
|
||||
#region Logging
|
||||
|
||||
private static readonly Common.Logging.ILog LOG = Common.Logging.LogManager.GetLogger(typeof (TransactionSynchronizationManager));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private static readonly string syncsDataSlotName = "Spring.Transactions:syncList";
|
||||
|
||||
private static readonly string resourcesDataSlotName = "Spring.Transactions:resources";
|
||||
|
||||
private static readonly string currentTxReadOnlyDataSlotName = "Spring.Transactions:currentTxReadOnly";
|
||||
|
||||
private static readonly string currentTxNameDataSlotName = "Spring.Transactions:currentTxName";
|
||||
|
||||
private static readonly string currentTxIsolationLevelDataSlotName = "Spring.Transactions:currentTxIsolationLevel";
|
||||
|
||||
private static readonly string actualTxActiveDataSlotName = "Spring.Transactions:actualTxActive";
|
||||
|
||||
private static IComparer syncComparer = new OrderComparator();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Management of transaction-associated resource handles
|
||||
/// <summary>
|
||||
/// Return all resources that are bound to the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>Main for debugging purposes. Resource manager should always
|
||||
/// invoke HasResource for a specific resource key that they are interested in.
|
||||
/// </remarks>
|
||||
/// <returns>IDictionary with resource keys and resource objects or empty
|
||||
/// dictionary if none is bound.</returns>
|
||||
public static IDictionary ResourceDictionary
|
||||
{
|
||||
get
|
||||
{
|
||||
IDictionary resources = LogicalThreadContext.GetData(resourcesDataSlotName) as IDictionary;
|
||||
if (resources != null)
|
||||
{
|
||||
//TODO add readonly wrapper in Spring.Collections.
|
||||
return resources;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Hashtable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if there is a resource for the given key bound to the current thread.
|
||||
/// </summary>
|
||||
/// <param name="key">key to check</param>
|
||||
/// <returns>if there is a value bound to the current thread</returns>
|
||||
public static bool HasResource(Object key)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(key, "Key must not be null");
|
||||
return ResourceDictionary.Contains(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve a resource for the given key that is bound to the current thread.
|
||||
/// </summary>
|
||||
/// <param name="key">key to check</param>
|
||||
/// <returns>a value bound to the current thread, or null if none.</returns>
|
||||
public static object GetResource(Object key)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(key, "Key must not be null");
|
||||
IDictionary resources = LogicalThreadContext.GetData(resourcesDataSlotName) as IDictionary;
|
||||
if (resources == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//Check for contains since indexer returning null behavior changes in 2.0
|
||||
if (!resources.Contains(key))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
object val = resources[key];
|
||||
|
||||
if (val != null && LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Retrieved value [" + Describe(val) + "] for key [" + Describe(key) + "] bound to thread [" +
|
||||
SystemUtils.ThreadId + "]");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bind the given resource for teh given key to the current thread
|
||||
/// </summary>
|
||||
/// <param name="key">key to bind the value to</param>
|
||||
/// <param name="value">value to bind</param>
|
||||
public static void BindResource(Object key, Object value)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(key, "Key value for thread local storage of transactional resources must not be null");
|
||||
AssertUtils.ArgumentNotNull(value, "Transactional resource to bind to thread local storage must not be null" );
|
||||
|
||||
IDictionary resources = LogicalThreadContext.GetData(resourcesDataSlotName) as IDictionary;
|
||||
//Set thread local resource storage if not found
|
||||
if (resources == null)
|
||||
{
|
||||
resources = new Hashtable();
|
||||
LogicalThreadContext.SetData(resourcesDataSlotName, resources);
|
||||
}
|
||||
if (resources.Contains(key))
|
||||
{
|
||||
throw new InvalidOperationException("Already value [" + resources[key] + "] for key [" + key +
|
||||
"] bound to thread [" + SystemUtils.ThreadId + "]");
|
||||
}
|
||||
resources.Add(key, value);
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Bound value [" + Describe(value) + "] for key [" + Describe(key) + "] to thread [" +
|
||||
SystemUtils.ThreadId + "]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Unbind a resource for the given key from the current thread
|
||||
/// </summary>
|
||||
/// <param name="key">key to check</param>
|
||||
/// <returns>the previously bound value</returns>
|
||||
/// <exception cref="InvalidOperationException">if there is no value bound to the thread</exception>
|
||||
public static object UnbindResource(Object key)
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(key, "Key must not be null");
|
||||
|
||||
IDictionary resources = LogicalThreadContext.GetData(resourcesDataSlotName) as IDictionary;
|
||||
if (resources == null || !resources.Contains(key))
|
||||
{
|
||||
throw new InvalidOperationException("No value for key [" + key + "] bound to thread [" +
|
||||
SystemUtils.ThreadId + "]");
|
||||
}
|
||||
Object val = resources[key];
|
||||
resources.Remove(key);
|
||||
if (resources.Count == 0)
|
||||
{
|
||||
LogicalThreadContext.FreeNamedDataSlot(resourcesDataSlotName);
|
||||
}
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Removed value [" + Describe(val) + "] for key [" + Describe(key) + "] from thread [" +
|
||||
SystemUtils.ThreadId + "]");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Activate transaction synchronization for the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Called by transaction manager at the beginning of a transaction.
|
||||
/// </remarks>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If synchronization is already active.
|
||||
/// </exception>
|
||||
public static void InitSynchronization()
|
||||
{
|
||||
if ( SynchronizationActive )
|
||||
{
|
||||
throw new InvalidOperationException( "Cannot activate transaction synchronization - already active" );
|
||||
}
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Initializing transaction synchronization");
|
||||
}
|
||||
ArrayList syncs = new ArrayList();
|
||||
LogicalThreadContext.SetData(syncsDataSlotName, syncs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivate transaction synchronization for the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Called by transaction manager on transaction cleanup.
|
||||
/// </remarks>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If synchronization is not active.
|
||||
/// </exception>
|
||||
public static void ClearSynchronization()
|
||||
{
|
||||
if ( !SynchronizationActive )
|
||||
{
|
||||
throw new InvalidOperationException( "Cannot deactivate transaction synchronization - not active" );
|
||||
}
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.Debug("Clearing transaction synchronization");
|
||||
}
|
||||
LogicalThreadContext.FreeNamedDataSlot(syncsDataSlotName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the entire transaction synchronization state for the current thread, registered
|
||||
/// synchronizations as well as the various transaction characteristics.
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
ClearSynchronization();
|
||||
CurrentTransactionName = null;
|
||||
CurrentTransactionReadOnly = false;
|
||||
CurrentTransactionIsolationLevel = IsolationLevel.Unspecified;
|
||||
ActualTransactionActive = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a new transaction synchronization for the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Typically called by resource management code.
|
||||
/// </remarks>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If synchronization is not active.
|
||||
/// </exception>
|
||||
public static void RegisterSynchronization( ITransactionSynchronization synchronization )
|
||||
{
|
||||
AssertUtils.ArgumentNotNull(synchronization, "TransactionSynchronization must not be null");
|
||||
if ( !SynchronizationActive )
|
||||
{
|
||||
throw new InvalidOperationException( "Transaction synchronization is not active" );
|
||||
}
|
||||
ArrayList syncs = LogicalThreadContext.GetData(syncsDataSlotName) as ArrayList;
|
||||
if (syncs != null)
|
||||
{
|
||||
object root = syncs.SyncRoot;
|
||||
lock (root)
|
||||
{
|
||||
syncs.Add(synchronization);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string Describe(object obj)
|
||||
{
|
||||
return obj == null ? "" : obj + "@" + obj.GetHashCode().ToString("X");
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Return an unmodifiable list of all registered synchronizations
|
||||
/// for the current thread.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A list of <see cref="Spring.Transaction.Support.ITransactionSynchronization"/>
|
||||
/// instances.
|
||||
/// </returns>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// If synchronization is not active.
|
||||
/// </exception>
|
||||
public static IList Synchronizations
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( ! SynchronizationActive )
|
||||
{
|
||||
throw new InvalidOperationException( "Transaction synchronization is not active" );
|
||||
}
|
||||
ArrayList syncs = LogicalThreadContext.GetData(syncsDataSlotName) as ArrayList;
|
||||
if (syncs != null)
|
||||
{
|
||||
// Sort lazily here, not in registerSynchronization.
|
||||
object root = syncs.SyncRoot;
|
||||
lock (root)
|
||||
{
|
||||
// #SPRNET-1160, tx Ben Rowlands
|
||||
CollectionUtils.StableSortInPlace(syncs, syncComparer);
|
||||
}
|
||||
|
||||
// Return unmodifiable snapshot, to avoid exceptions
|
||||
// while iterating and invoking synchronization callbacks that in turn
|
||||
// might register further synchronizations.
|
||||
return ArrayList.ReadOnly(syncs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ArrayList.ReadOnly(new ArrayList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return if transaction synchronization is active for the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Can be called before
|
||||
/// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager.RegisterSynchronization">InitSynchronization</see>
|
||||
/// to avoid unnecessary instance creation.
|
||||
/// </remarks>
|
||||
public static bool SynchronizationActive
|
||||
{
|
||||
get
|
||||
{
|
||||
IList syncs = LogicalThreadContext.GetData(syncsDataSlotName) as IList;
|
||||
return syncs != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the
|
||||
/// current transaction is read only.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Called by transaction manager on transaction begin and on cleanup.
|
||||
/// Return whether the current transaction is marked as read-only.
|
||||
/// To be called by resource management code when preparing a newly
|
||||
/// created resource (for example, a Hibernate Session).
|
||||
/// <p>Note that transaction synchronizations receive the read-only flag
|
||||
/// as argument for the <code>beforeCommit</code> callback, to be able
|
||||
/// to suppress change detection on commit. The present method is meant
|
||||
/// to be used for earlier read-only checks, for example to set the
|
||||
/// flush mode of a Hibernate Session to FlushMode.Never upfront.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// <c>true</c> if current transaction read only; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public static bool CurrentTransactionReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return LogicalThreadContext.GetData(currentTxReadOnlyDataSlotName) != null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
LogicalThreadContext.SetData(currentTxReadOnlyDataSlotName, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogicalThreadContext.FreeNamedDataSlot(currentTxReadOnlyDataSlotName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the current transaction, if any.
|
||||
/// </summary>
|
||||
/// <remarks>Called by the transaction manager on transaction begin and on cleanup.
|
||||
/// To be called by resource management code for optimizations per use case, for
|
||||
/// example to optimize fetch strategies for specific named transactions.</remarks>
|
||||
/// <value>The name of the current transactio or null if none set.</value>
|
||||
public static string CurrentTransactionName
|
||||
{
|
||||
get
|
||||
{
|
||||
return LogicalThreadContext.GetData(currentTxNameDataSlotName) as string;
|
||||
}
|
||||
set
|
||||
{
|
||||
LogicalThreadContext.SetData(currentTxNameDataSlotName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether there currently is an actual transaction
|
||||
/// active.
|
||||
/// </summary>
|
||||
/// <remarks>This indicates wheter the current thread is associated with an actual
|
||||
/// transaction rather than just with active transaction synchronization.
|
||||
/// <para>Called by the transaction manager on transaction begin and on cleanup.</para>
|
||||
/// <para>To be called by resource management code that wants to discriminate between
|
||||
/// active transaction synchronization (with or without backing resource transaction;
|
||||
/// also on PROPAGATION_SUPPORTS) and an actual transaction being active; on
|
||||
/// PROPAGATION_REQUIRES, PROPAGATION_REQUIRES_NEW, etC)</para></remarks>
|
||||
/// <value>
|
||||
/// <c>true</c> if [actual transaction active]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public static bool ActualTransactionActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return LogicalThreadContext.GetData(actualTxActiveDataSlotName) != null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
LogicalThreadContext.SetData(actualTxActiveDataSlotName, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogicalThreadContext.FreeNamedDataSlot(actualTxActiveDataSlotName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current transaction isolation level, if any.
|
||||
/// </summary>
|
||||
/// <remarks>Called by the transaction manager on transaction begin and on cleanup.</remarks>
|
||||
/// <value>The current transaction isolation level. If no current transaction is
|
||||
/// active, retrun IsolationLevel.Unspecified</value>
|
||||
public static IsolationLevel CurrentTransactionIsolationLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
object data =
|
||||
LogicalThreadContext.GetData(currentTxIsolationLevelDataSlotName);
|
||||
if (data != null)
|
||||
{
|
||||
return (IsolationLevel) data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IsolationLevel.Unspecified;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
LogicalThreadContext.SetData(currentTxIsolationLevelDataSlotName, value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
// Return unmodifiable snapshot, to avoid exceptions
|
||||
// while iterating and invoking synchronization callbacks that in turn
|
||||
// might register further synchronizations.
|
||||
return ArrayList.ReadOnly(syncs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ArrayList.ReadOnly(new ArrayList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return if transaction synchronization is active for the current thread.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Can be called before
|
||||
/// <see cref="Spring.Transaction.Support.TransactionSynchronizationManager.RegisterSynchronization">InitSynchronization</see>
|
||||
/// to avoid unnecessary instance creation.
|
||||
/// </remarks>
|
||||
public static bool SynchronizationActive
|
||||
{
|
||||
get
|
||||
{
|
||||
IList syncs = LogicalThreadContext.GetData(syncsDataSlotName) as IList;
|
||||
return syncs != null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the
|
||||
/// current transaction is read only.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Called by transaction manager on transaction begin and on cleanup.
|
||||
/// Return whether the current transaction is marked as read-only.
|
||||
/// To be called by resource management code when preparing a newly
|
||||
/// created resource (for example, a Hibernate Session).
|
||||
/// <p>Note that transaction synchronizations receive the read-only flag
|
||||
/// as argument for the <code>beforeCommit</code> callback, to be able
|
||||
/// to suppress change detection on commit. The present method is meant
|
||||
/// to be used for earlier read-only checks, for example to set the
|
||||
/// flush mode of a Hibernate Session to FlushMode.Never upfront.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <value>
|
||||
/// <c>true</c> if current transaction read only; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public static bool CurrentTransactionReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return LogicalThreadContext.GetData(currentTxReadOnlyDataSlotName) != null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
LogicalThreadContext.SetData(currentTxReadOnlyDataSlotName, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogicalThreadContext.FreeNamedDataSlot(currentTxReadOnlyDataSlotName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the current transaction, if any.
|
||||
/// </summary>
|
||||
/// <remarks>Called by the transaction manager on transaction begin and on cleanup.
|
||||
/// To be called by resource management code for optimizations per use case, for
|
||||
/// example to optimize fetch strategies for specific named transactions.</remarks>
|
||||
/// <value>The name of the current transactio or null if none set.</value>
|
||||
public static string CurrentTransactionName
|
||||
{
|
||||
get
|
||||
{
|
||||
return LogicalThreadContext.GetData(currentTxNameDataSlotName) as string;
|
||||
}
|
||||
set
|
||||
{
|
||||
LogicalThreadContext.SetData(currentTxNameDataSlotName, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether there currently is an actual transaction
|
||||
/// active.
|
||||
/// </summary>
|
||||
/// <remarks>This indicates wheter the current thread is associated with an actual
|
||||
/// transaction rather than just with active transaction synchronization.
|
||||
/// <para>Called by the transaction manager on transaction begin and on cleanup.</para>
|
||||
/// <para>To be called by resource management code that wants to discriminate between
|
||||
/// active transaction synchronization (with or without backing resource transaction;
|
||||
/// also on PROPAGATION_SUPPORTS) and an actual transaction being active; on
|
||||
/// PROPAGATION_REQUIRES, PROPAGATION_REQUIRES_NEW, etC)</para></remarks>
|
||||
/// <value>
|
||||
/// <c>true</c> if [actual transaction active]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public static bool ActualTransactionActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return LogicalThreadContext.GetData(actualTxActiveDataSlotName) != null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
LogicalThreadContext.SetData(actualTxActiveDataSlotName, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogicalThreadContext.FreeNamedDataSlot(actualTxActiveDataSlotName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current transaction isolation level, if any.
|
||||
/// </summary>
|
||||
/// <remarks>Called by the transaction manager on transaction begin and on cleanup.</remarks>
|
||||
/// <value>The current transaction isolation level. If no current transaction is
|
||||
/// active, retrun IsolationLevel.Unspecified</value>
|
||||
public static IsolationLevel CurrentTransactionIsolationLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
object data =
|
||||
LogicalThreadContext.GetData(currentTxIsolationLevelDataSlotName);
|
||||
if (data != null)
|
||||
{
|
||||
return (IsolationLevel) data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IsolationLevel.Unspecified;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
LogicalThreadContext.SetData(currentTxIsolationLevelDataSlotName, value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,29 @@ namespace Spring.Data.NHibernate
|
||||
[TestFixture]
|
||||
public class HibernateTransactionManagerTests
|
||||
{
|
||||
private class TestableHibernateTransactionManager : HibernateTransactionManager
|
||||
{
|
||||
private IDbTransaction _stubbedTransactionWithExpectedConnection;
|
||||
|
||||
public TestableHibernateTransactionManager()
|
||||
{
|
||||
}
|
||||
|
||||
public TestableHibernateTransactionManager(ISessionFactory sessionFactory) : base(sessionFactory)
|
||||
{
|
||||
}
|
||||
|
||||
public IDbTransaction StubbedTransactionThatReturnsExpectedConnection
|
||||
{
|
||||
set { _stubbedTransactionWithExpectedConnection = value; }
|
||||
}
|
||||
|
||||
protected override IDbTransaction GetIDbTransaction(ITransaction hibernateTx)
|
||||
{
|
||||
return _stubbedTransactionWithExpectedConnection;
|
||||
}
|
||||
}
|
||||
|
||||
private MockRepository mocks;
|
||||
|
||||
[SetUp]
|
||||
@@ -88,6 +111,7 @@ namespace Spring.Data.NHibernate
|
||||
Assert.IsNotNull(sfProxy);
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager();
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
tm.AdoExceptionTranslator = new FallbackExceptionTranslator();
|
||||
tm.SessionFactory = sfProxy;
|
||||
tm.DbProvider = provider;
|
||||
@@ -95,19 +119,19 @@ namespace Spring.Data.NHibernate
|
||||
|
||||
tt.TransactionIsolationLevel = IsolationLevel.Serializable;
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sfProxy),"Hasn't thread session");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(provider), "Hasn't thread db provider");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.ActualTransactionActive, "Actual transaction not active");
|
||||
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.IsTrue(!TransactionSynchronizationManager.HasResource(sfProxy), "Hasn't thread session");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(provider), "Hasn't thread db provider");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.ActualTransactionActive, "Actual transaction not active");
|
||||
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();
|
||||
@@ -124,6 +148,7 @@ namespace Spring.Data.NHibernate
|
||||
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())
|
||||
{
|
||||
@@ -132,6 +157,9 @@ namespace Spring.Data.NHibernate
|
||||
Expect.Call(session.BeginTransaction(IsolationLevel.ReadCommitted)).Return(transaction);
|
||||
Expect.Call(session.IsOpen).Return(true);
|
||||
|
||||
Expect.Call(adoTransaction.Connection).Return(connection);
|
||||
LastCall.On(adoTransaction).Repeat.Once();
|
||||
|
||||
transaction.Rollback();
|
||||
LastCall.On(transaction).Repeat.Once();
|
||||
|
||||
@@ -139,11 +167,14 @@ namespace Spring.Data.NHibernate
|
||||
}
|
||||
mocks.ReplayAll();
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
TestableHibernateTransactionManager tm = new TestableHibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
tm.StubbedTransactionThatReturnsExpectedConnection = adoTransaction;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
|
||||
try
|
||||
{
|
||||
@@ -154,8 +185,8 @@ namespace Spring.Data.NHibernate
|
||||
|
||||
}
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(provider), "Hasn't thread db provider");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.HasResource(provider), "Hasn't thread db provider");
|
||||
|
||||
mocks.VerifyAll();
|
||||
}
|
||||
@@ -167,6 +198,7 @@ namespace Spring.Data.NHibernate
|
||||
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())
|
||||
{
|
||||
@@ -177,6 +209,10 @@ namespace Spring.Data.NHibernate
|
||||
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);
|
||||
@@ -184,14 +220,17 @@ namespace Spring.Data.NHibernate
|
||||
mocks.ReplayAll();
|
||||
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
TestableHibernateTransactionManager tm = new TestableHibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
tm.StubbedTransactionThatReturnsExpectedConnection = adoTransaction;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.HasResource(sessionFactory), "Shouldn't have a thread session");
|
||||
|
||||
tt.Execute(new TransactionRollbackOnlyTxCallback(sessionFactory));
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(sessionFactory), "Hasn't thread session");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.HasResource(sessionFactory), "Shouldn't have a thread session");
|
||||
|
||||
mocks.VerifyAll();
|
||||
|
||||
@@ -222,6 +261,8 @@ namespace Spring.Data.NHibernate
|
||||
mocks.ReplayAll();
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
IList list = new ArrayList();
|
||||
list.Add("test");
|
||||
@@ -240,6 +281,7 @@ namespace Spring.Data.NHibernate
|
||||
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())
|
||||
{
|
||||
@@ -249,6 +291,9 @@ namespace Spring.Data.NHibernate
|
||||
Expect.Call(session.IsOpen).Return(true);
|
||||
Expect.Call(session.FlushMode).Return(FlushMode.Auto);
|
||||
|
||||
Expect.Call(adoTransaction.Connection).Return(connection);
|
||||
LastCall.On(adoTransaction).Repeat.Once();
|
||||
|
||||
transaction.Rollback();
|
||||
LastCall.On(transaction).Repeat.Once();
|
||||
Expect.Call(session.Close()).Return(null);
|
||||
@@ -256,7 +301,10 @@ namespace Spring.Data.NHibernate
|
||||
mocks.ReplayAll();
|
||||
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
TestableHibernateTransactionManager tm = new TestableHibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
tm.StubbedTransactionThatReturnsExpectedConnection = adoTransaction;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
try
|
||||
{
|
||||
@@ -278,6 +326,7 @@ namespace Spring.Data.NHibernate
|
||||
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())
|
||||
{
|
||||
@@ -286,6 +335,9 @@ namespace Spring.Data.NHibernate
|
||||
Expect.Call(session.BeginTransaction(IsolationLevel.ReadCommitted)).Return(transaction);
|
||||
Expect.Call(session.IsOpen).Return(true);
|
||||
|
||||
Expect.Call(adoTransaction.Connection).Return(connection);
|
||||
LastCall.On(adoTransaction).Repeat.Once();
|
||||
|
||||
transaction.Rollback();
|
||||
LastCall.On(transaction).Repeat.Once();
|
||||
Expect.Call(session.Close()).Return(null);
|
||||
@@ -293,7 +345,10 @@ namespace Spring.Data.NHibernate
|
||||
mocks.ReplayAll();
|
||||
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
TestableHibernateTransactionManager tm = new TestableHibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
tm.StubbedTransactionThatReturnsExpectedConnection = adoTransaction;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
IList list = new ArrayList();
|
||||
list.Add("test");
|
||||
@@ -345,6 +400,8 @@ namespace Spring.Data.NHibernate
|
||||
mocks.ReplayAll();
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
|
||||
@@ -389,6 +446,8 @@ namespace Spring.Data.NHibernate
|
||||
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
|
||||
@@ -431,6 +490,8 @@ namespace Spring.Data.NHibernate
|
||||
Assert.IsNotNull(sfProxy);
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.Supports;
|
||||
|
||||
@@ -485,6 +546,7 @@ namespace Spring.Data.NHibernate
|
||||
Assert.IsNotNull(sfProxy);
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.Supports;
|
||||
@@ -536,6 +598,8 @@ namespace Spring.Data.NHibernate
|
||||
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())
|
||||
{
|
||||
@@ -562,6 +626,9 @@ namespace Spring.Data.NHibernate
|
||||
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);
|
||||
@@ -572,8 +639,10 @@ namespace Spring.Data.NHibernate
|
||||
mocks.ReplayAll();
|
||||
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
|
||||
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");
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{93FED0CE-0B01-43AF-8CB1-244CC7C3308B}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Spring</RootNamespace>
|
||||
<AssemblyName>Spring.Data.NHibernate30.Integration.Tests</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<UpgradeBackupLocation />
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\..\build\VS.Net.2008\Spring.Data.NHibernate30.Integration.Tests\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG;NET_2_0,NH_2_0,NH_2_1</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\..\..\build\VS.Net.2008\Spring.Data.NHibernate30.Integration.Tests\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NET_2_0,NH_2_0,NH_2_1</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Common.Logging, Version=1.0.2.0, Culture=neutral, PublicKeyToken=af08829b84f0328e">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\Common.Logging.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Iesi.Collections, Version=1.0.0.3, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\NHibernate30\net\3.5\Iesi.Collections.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\NHibernate30\net\3.5\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NHibernate, Version=1.2.1.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\NHibernate30\net\3.5\NHibernate.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.4.1.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\lib\Net\2.0\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\AccountCreditDao.cs">
|
||||
<Link>Data\NHibernate\AccountCreditDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\AccountDebitDao.cs">
|
||||
<Link>Data\NHibernate\AccountDebitDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\AccountManager.cs">
|
||||
<Link>Data\NHibernate\AccountManager.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\AuditDao.cs">
|
||||
<Link>Data\NHibernate\AuditDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\Credit.cs">
|
||||
<Link>Data\NHibernate\Credit.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\DbProviderTemplateTests.cs">
|
||||
<Link>Data\NHibernate\DbProviderTemplateTests.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\Debit.cs">
|
||||
<Link>Data\NHibernate\Debit.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\IAccountCreditDao.cs">
|
||||
<Link>Data\NHibernate\IAccountCreditDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\IAccountDebitDao.cs">
|
||||
<Link>Data\NHibernate\IAccountDebitDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\IAccountManager.cs">
|
||||
<Link>Data\NHibernate\IAccountManager.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\IAuditDao.cs">
|
||||
<Link>Data\NHibernate\IAuditDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\ITestObjectDao.cs">
|
||||
<Link>Data\NHibernate\ITestObjectDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\MultipleDbTests.cs">
|
||||
<Link>Data\NHibernate\MultipleDbTests.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\NativeNHTestObjectDao.cs">
|
||||
<Link>Data\NHibernate\NativeNHTestObjectDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\NativeNHTests.cs">
|
||||
<Link>Data\NHibernate\NativeNHTests.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\NHDAOTests.cs">
|
||||
<Link>Data\NHibernate\NHDAOTests.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\NHTestObjectDao.cs">
|
||||
<Link>Data\NHibernate\NHTestObjectDao.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\TemplateTests.cs">
|
||||
<Link>Data\NHibernate\TemplateTests.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\TestObject.cs">
|
||||
<Link>Data\NHibernate\TestObject.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate21.Integration.Tests\Data\NHibernate\HibernateTxScopeTransactionManagerTests.cs">
|
||||
<Link>Data\NHibernate\HibernateTxScopeTransactionManagerTests.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\Spring.Data.NHibernate.Integration.Tests\Data\NHibernate\creditdebit.sql">
|
||||
<Link>Data\NHibernate\creditdebit.sql</Link>
|
||||
</None>
|
||||
<None Include="Spring.Data.NHibernate30.Integration.Tests.dll.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Aop\Spring.Aop.2010.csproj">
|
||||
<Project>{3A3A4E65-45A6-4B20-B460-0BEDC302C02C}</Project>
|
||||
<Name>Spring.Aop.2010</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Core\Spring.Core.2010.csproj">
|
||||
<Project>{710961A3-0DF4-49E4-A26E-F5B9C044AC84}</Project>
|
||||
<Name>Spring.Core.2010</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Data.NHibernate30\Spring.Data.NHibernate30.2010.csproj">
|
||||
<Project>{009247FE-CBAD-40FF-ADC3-D7F28B270071}</Project>
|
||||
<Name>Spring.Data.NHibernate30.2010</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\src\Spring\Spring.Data\Spring.Data.2010.csproj">
|
||||
<Project>{AE00E5AB-C39A-436F-86D2-33BFE33E2E40}</Project>
|
||||
<Name>Spring.Data.2010</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Data\NHibernate\Credit.hbm.xml" />
|
||||
<EmbeddedResource Include="Data\NHibernate\Debit.hbm.xml" />
|
||||
<EmbeddedResource Include="Data\NHibernate\MultipleDbTests.xml" />
|
||||
<EmbeddedResource Include="Data\NHibernate\TestObject.hbm.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Data\NHibernate\NHDAOTests.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Data\NHibernate\dbProviderTemplateTests.xml" />
|
||||
<EmbeddedResource Include="Data\NHibernate\templateTests.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Windows Installer 3.1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\Spring.Data.NHibernate21.Integration.Tests\Data\NHibernate\HibernateTxScopeTransactionManagerTests.xml">
|
||||
<Link>Data\NHibernate\HibernateTxScopeTransactionManagerTests.xml</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>echo "Copying .xml files for tests"
|
||||
xcopy "$(ProjectDir)Data" ..\..\..\..\build\VS.Net.2008\Spring.Data.NHibernate30.Integration.Tests\$(ConfigurationName)\ /y /s /q /d
|
||||
xcopy "$(ProjectDir)$(TargetFileName).config" ..\..\..\..\build\VS.Net.2008\Spring.Data.NHibernate30.Integration.Tests\$(ConfigurationName)\ /y /s /q</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -86,6 +86,7 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
@@ -127,6 +128,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(dbProvider), "Hasn't thread db provider");
|
||||
@@ -171,9 +174,10 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(dbProvider), "Hasn't thread db provider");
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.HasResource(dbProvider), "Hasn't thread db provider");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
|
||||
ITransactionStatus ts = tm.GetTransaction(new DefaultTransactionDefinition());
|
||||
TestTransactionSynchronization synch =
|
||||
@@ -201,7 +205,7 @@ namespace Spring.Data
|
||||
Assert.IsTrue(outerTransactionBoundaryReached);
|
||||
}
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(dbProvider), "Hasn't thread db provider");
|
||||
Assert.IsFalse(TransactionSynchronizationManager.HasResource(dbProvider), "Hasn't thread db provider");
|
||||
Assert.IsFalse(synch.beforeCommitCalled);
|
||||
Assert.IsTrue(synch.beforeCompletionCalled);
|
||||
Assert.IsFalse(synch.afterCommitCalled);
|
||||
@@ -249,6 +253,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
@@ -293,10 +299,14 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
|
||||
AdoPlatformTransactionManager tm2 = new AdoPlatformTransactionManager(dbProvider2);
|
||||
tm2.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt2 = new TransactionTemplate(tm2);
|
||||
tt2.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
|
||||
@@ -342,6 +352,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
|
||||
@@ -393,6 +405,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(dbProvider), "Hasn't thread db provider");
|
||||
@@ -428,6 +442,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(dbProvider), "Hasn't thread db provider");
|
||||
@@ -475,6 +491,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.Supports;
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.HasResource(dbProvider), "Hasn't thread db provider");
|
||||
@@ -513,6 +531,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
tt.TransactionIsolationLevel = IsolationLevel.Serializable;
|
||||
@@ -573,6 +593,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.TransactionTimeout = timeout;
|
||||
|
||||
@@ -616,6 +638,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
try
|
||||
{
|
||||
@@ -661,6 +685,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
try
|
||||
@@ -703,6 +729,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
tm.RollbackOnCommitFailure = true;
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
@@ -747,6 +775,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
try
|
||||
@@ -778,6 +808,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.Supports;
|
||||
|
||||
@@ -797,6 +829,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.NotSupported;
|
||||
|
||||
@@ -816,6 +850,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.Never;
|
||||
|
||||
@@ -852,6 +888,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.Nested;
|
||||
|
||||
@@ -896,6 +934,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.Nested;
|
||||
|
||||
@@ -941,6 +981,8 @@ namespace Spring.Data
|
||||
mocks.ReplayAll();
|
||||
|
||||
AdoPlatformTransactionManager tm = new AdoPlatformTransactionManager(dbProvider);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.Nested;
|
||||
|
||||
|
||||
@@ -78,8 +78,10 @@ namespace Spring.Data.Core
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
IPlatformTransactionManager tm = new ServiceDomainPlatformTransactionManager(txAdapter);
|
||||
ServiceDomainPlatformTransactionManager tm = new ServiceDomainPlatformTransactionManager(txAdapter);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
tt.Execute(new TransactionDelegate(TransactionCommitMethod));
|
||||
|
||||
Assert.IsFalse(TransactionSynchronizationManager.SynchronizationActive);
|
||||
@@ -117,7 +119,9 @@ namespace Spring.Data.Core
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
IPlatformTransactionManager tm = new ServiceDomainPlatformTransactionManager(txAdapter);
|
||||
ServiceDomainPlatformTransactionManager tm = new ServiceDomainPlatformTransactionManager(txAdapter);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
@@ -183,7 +187,9 @@ namespace Spring.Data.Core
|
||||
|
||||
mocks.ReplayAll();
|
||||
|
||||
IPlatformTransactionManager tm = new ServiceDomainPlatformTransactionManager(txAdapter);
|
||||
ServiceDomainPlatformTransactionManager tm = new ServiceDomainPlatformTransactionManager(txAdapter);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
tt.Execute(new PropagationRequiresNewWithExistingTransactionCallbackSD(tt));
|
||||
|
||||
@@ -65,6 +65,8 @@ namespace Spring.Data.Core
|
||||
public void Commit()
|
||||
{
|
||||
TxScopeTransactionManager tm = new TxScopeTransactionManager();
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
//tt.Name = "txName";
|
||||
@@ -91,6 +93,8 @@ namespace Spring.Data.Core
|
||||
public void TransactionInformation()
|
||||
{
|
||||
TxScopeTransactionManager tm = new TxScopeTransactionManager();
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.TransactionIsolationLevel = System.Data.IsolationLevel.ReadUncommitted;
|
||||
tt.Execute(TransactionInformationTxDelegate);
|
||||
@@ -121,6 +125,8 @@ namespace Spring.Data.Core
|
||||
|
||||
|
||||
TxScopeTransactionManager tm = new TxScopeTransactionManager();
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.TransactionTimeout = 10;
|
||||
tt.Name = "txName";
|
||||
|
||||
@@ -68,7 +68,9 @@ namespace Spring.Data.Core
|
||||
}
|
||||
mocks.ReplayAll();
|
||||
|
||||
IPlatformTransactionManager tm = new TxScopeTransactionManager(txAdapter);
|
||||
TxScopeTransactionManager tm = new TxScopeTransactionManager(txAdapter);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.Execute(delegate(ITransactionStatus status)
|
||||
{
|
||||
@@ -100,7 +102,9 @@ namespace Spring.Data.Core
|
||||
}
|
||||
mocks.ReplayAll();
|
||||
|
||||
IPlatformTransactionManager tm = new TxScopeTransactionManager(txAdapter);
|
||||
TxScopeTransactionManager tm = new TxScopeTransactionManager(txAdapter);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
|
||||
Assert.IsTrue(!TransactionSynchronizationManager.SynchronizationActive, "Synchronizations not active");
|
||||
@@ -155,7 +159,9 @@ namespace Spring.Data.Core
|
||||
}
|
||||
mocks.ReplayAll();
|
||||
|
||||
IPlatformTransactionManager tm = new TxScopeTransactionManager(txAdapter);
|
||||
TxScopeTransactionManager tm = new TxScopeTransactionManager(txAdapter);
|
||||
tm.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
tt.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
tt.Execute(delegate(ITransactionStatus status)
|
||||
|
||||
@@ -3,218 +3,219 @@ using NUnit.Framework;
|
||||
|
||||
namespace Spring.Transaction.Support
|
||||
{
|
||||
[TestFixture]
|
||||
public class AbstractPlatformTransactionManagerTests
|
||||
{
|
||||
private MockTxnPlatformMgrAbstract _mockTxnMgr;
|
||||
|
||||
[SetUp]
|
||||
public void Init()
|
||||
{
|
||||
_mockTxnMgr = new MockTxnPlatformMgrAbstract();
|
||||
if ( TransactionSynchronizationManager.SynchronizationActive )
|
||||
{
|
||||
TransactionSynchronizationManager.ClearSynchronization();
|
||||
}
|
||||
}
|
||||
[TearDown]
|
||||
public void Destroy()
|
||||
{
|
||||
_mockTxnMgr.Verify();
|
||||
_mockTxnMgr = null;
|
||||
if ( TransactionSynchronizationManager.SynchronizationActive )
|
||||
{
|
||||
TransactionSynchronizationManager.ClearSynchronization();
|
||||
}
|
||||
}
|
||||
[Test]
|
||||
public void VanillaProperties()
|
||||
{
|
||||
Assert.AreEqual( TransactionSynchronizationState.Always, _mockTxnMgr.TransactionSynchronization);
|
||||
Assert.IsTrue(!_mockTxnMgr.NestedTransactionsAllowed);
|
||||
Assert.IsTrue(!_mockTxnMgr.RollbackOnCommitFailure);
|
||||
|
||||
_mockTxnMgr.NestedTransactionsAllowed = true;
|
||||
_mockTxnMgr.RollbackOnCommitFailure = true;
|
||||
_mockTxnMgr.TransactionSynchronization = TransactionSynchronizationState.OnActualTransaction;
|
||||
|
||||
Assert.AreEqual( TransactionSynchronizationState.OnActualTransaction, _mockTxnMgr.TransactionSynchronization);
|
||||
Assert.IsTrue(_mockTxnMgr.NestedTransactionsAllowed);
|
||||
Assert.IsTrue(_mockTxnMgr.RollbackOnCommitFailure);
|
||||
}
|
||||
[Test]
|
||||
[ExpectedException(typeof(InvalidTimeoutException), ExpectedMessage="Invalid transaction timeout")]
|
||||
public void DefinitionInvalidTimeoutException()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.TransactionTimeout = -1000;
|
||||
_mockTxnMgr.GetTransaction( def );
|
||||
}
|
||||
[Test]
|
||||
[ExpectedException(typeof(IllegalTransactionStateException), ExpectedMessage="Transaction propagation 'mandatory' but no existing transaction found")]
|
||||
public void DefinitionInvalidPropagationState()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Mandatory;
|
||||
_mockTxnMgr.GetTransaction( def );
|
||||
}
|
||||
[TestFixture]
|
||||
public class AbstractPlatformTransactionManagerTests
|
||||
{
|
||||
private MockTxnPlatformMgrAbstract _mockTxnMgr;
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(IllegalTransactionStateException), ExpectedMessage="Transaction propagation 'never' but existing transaction found.")]
|
||||
public void NeverPropagateState()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Never;
|
||||
setGeneralGetTransactionExpectations();
|
||||
_mockTxnMgr.GetTransaction(def);
|
||||
}
|
||||
[Test]
|
||||
[ExpectedException(typeof(NestedTransactionNotSupportedException), ExpectedMessage="Transaction manager does not allow nested transactions by default - specify 'NestedTransactionsAllowed' property with value 'true'")]
|
||||
public void NoNestedTransactionsAllowed()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Nested;
|
||||
setGeneralGetTransactionExpectations();
|
||||
_mockTxnMgr.GetTransaction(def);
|
||||
}
|
||||
[Test]
|
||||
public void TransactionSuspendedSuccessfully()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.NotSupported;
|
||||
def.ReadOnly = false;
|
||||
setGeneralGetTransactionExpectations();
|
||||
[SetUp]
|
||||
public void Init()
|
||||
{
|
||||
_mockTxnMgr = new MockTxnPlatformMgrAbstract();
|
||||
_mockTxnMgr.TransactionSynchronization = TransactionSynchronizationState.Always;
|
||||
if (TransactionSynchronizationManager.SynchronizationActive)
|
||||
{
|
||||
TransactionSynchronizationManager.ClearSynchronization();
|
||||
}
|
||||
}
|
||||
[TearDown]
|
||||
public void Destroy()
|
||||
{
|
||||
_mockTxnMgr.Verify();
|
||||
_mockTxnMgr = null;
|
||||
if (TransactionSynchronizationManager.SynchronizationActive)
|
||||
{
|
||||
TransactionSynchronizationManager.Clear();
|
||||
}
|
||||
}
|
||||
[Test]
|
||||
public void VanillaProperties()
|
||||
{
|
||||
Assert.AreEqual(TransactionSynchronizationState.Always, _mockTxnMgr.TransactionSynchronization);
|
||||
Assert.IsTrue(!_mockTxnMgr.NestedTransactionsAllowed);
|
||||
Assert.IsTrue(!_mockTxnMgr.RollbackOnCommitFailure);
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.IsNull( status.Transaction );
|
||||
Assert.IsTrue( !status.IsNewTransaction );
|
||||
Assert.IsTrue( status.NewSynchronization );
|
||||
Assert.IsTrue( !status.ReadOnly );
|
||||
Assert.IsNotNull( status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void TransactionCreatedSuccessfully()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
def.ReadOnly = false;
|
||||
_mockTxnMgr.NestedTransactionsAllowed = true;
|
||||
_mockTxnMgr.RollbackOnCommitFailure = true;
|
||||
_mockTxnMgr.TransactionSynchronization = TransactionSynchronizationState.OnActualTransaction;
|
||||
|
||||
setGeneralGetTransactionExpectations();
|
||||
Assert.AreEqual(TransactionSynchronizationState.OnActualTransaction, _mockTxnMgr.TransactionSynchronization);
|
||||
Assert.IsTrue(_mockTxnMgr.NestedTransactionsAllowed);
|
||||
Assert.IsTrue(_mockTxnMgr.RollbackOnCommitFailure);
|
||||
}
|
||||
[Test]
|
||||
[ExpectedException(typeof(InvalidTimeoutException), ExpectedMessage = "Invalid transaction timeout")]
|
||||
public void DefinitionInvalidTimeoutException()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.TransactionTimeout = -1000;
|
||||
_mockTxnMgr.GetTransaction(def);
|
||||
}
|
||||
[Test]
|
||||
[ExpectedException(typeof(IllegalTransactionStateException), ExpectedMessage = "Transaction propagation 'mandatory' but no existing transaction found")]
|
||||
public void DefinitionInvalidPropagationState()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Mandatory;
|
||||
_mockTxnMgr.GetTransaction(def);
|
||||
}
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.AreEqual( _mockTxnMgr.Transaction, status.Transaction );
|
||||
Assert.IsTrue( status.IsNewTransaction );
|
||||
Assert.IsTrue( status.NewSynchronization );
|
||||
Assert.IsTrue( !status.ReadOnly );
|
||||
Assert.IsNotNull( status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void NestedTransactionSuccessfully()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Nested;
|
||||
def.ReadOnly = false;
|
||||
[Test]
|
||||
[ExpectedException(typeof(IllegalTransactionStateException), ExpectedMessage = "Transaction propagation 'never' but existing transaction found.")]
|
||||
public void NeverPropagateState()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Never;
|
||||
setGeneralGetTransactionExpectations();
|
||||
_mockTxnMgr.GetTransaction(def);
|
||||
}
|
||||
[Test]
|
||||
[ExpectedException(typeof(NestedTransactionNotSupportedException), ExpectedMessage = "Transaction manager does not allow nested transactions by default - specify 'NestedTransactionsAllowed' property with value 'true'")]
|
||||
public void NoNestedTransactionsAllowed()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Nested;
|
||||
setGeneralGetTransactionExpectations();
|
||||
_mockTxnMgr.GetTransaction(def);
|
||||
}
|
||||
[Test]
|
||||
public void TransactionSuspendedSuccessfully()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.NotSupported;
|
||||
def.ReadOnly = false;
|
||||
setGeneralGetTransactionExpectations();
|
||||
|
||||
setGeneralGetTransactionExpectations();
|
||||
_mockTxnMgr.SetExpectedCalls( "DoBegin", 1 );
|
||||
_mockTxnMgr.Savepoints = false;
|
||||
_mockTxnMgr.NestedTransactionsAllowed = true;
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.IsNull(status.Transaction);
|
||||
Assert.IsTrue(!status.IsNewTransaction);
|
||||
Assert.IsTrue(status.NewSynchronization);
|
||||
Assert.IsTrue(!status.ReadOnly);
|
||||
Assert.IsNotNull(status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void TransactionCreatedSuccessfully()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.RequiresNew;
|
||||
def.ReadOnly = false;
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.AreEqual( _mockTxnMgr.Transaction, status.Transaction );
|
||||
Assert.IsTrue( status.IsNewTransaction );
|
||||
Assert.AreEqual( true, status.NewSynchronization );
|
||||
Assert.IsTrue( !status.ReadOnly );
|
||||
Assert.IsNull( status.SuspendedResources);
|
||||
}
|
||||
setGeneralGetTransactionExpectations();
|
||||
|
||||
[Test]
|
||||
public void NestedTransactionWithSavepoint()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Nested;
|
||||
def.ReadOnly = false;
|
||||
setVanillaGetTransactionExpectations();
|
||||
_mockTxnMgr.SetTransaction( new MyMockTxnObjectSavepointMgr());
|
||||
_mockTxnMgr.SetExpectedCalls("DoBegin", 0);
|
||||
_mockTxnMgr.Savepoints = true;
|
||||
_mockTxnMgr.NestedTransactionsAllowed = true;
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.AreEqual(_mockTxnMgr.Transaction, status.Transaction);
|
||||
Assert.IsTrue(status.IsNewTransaction);
|
||||
Assert.IsTrue(status.NewSynchronization);
|
||||
Assert.IsTrue(!status.ReadOnly);
|
||||
Assert.IsNotNull(status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void NestedTransactionSuccessfully()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Nested;
|
||||
def.ReadOnly = false;
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.AreEqual( _mockTxnMgr.Transaction, status.Transaction );
|
||||
Assert.IsFalse( status.IsNewTransaction );
|
||||
Assert.IsFalse( status.NewSynchronization );
|
||||
Assert.IsTrue( !status.ReadOnly );
|
||||
Assert.IsNull( status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void DefaultPropagationBehavior()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Required;
|
||||
def.ReadOnly = true;
|
||||
setGeneralGetTransactionExpectations();
|
||||
setGeneralGetTransactionExpectations();
|
||||
_mockTxnMgr.SetExpectedCalls("DoBegin", 1);
|
||||
_mockTxnMgr.Savepoints = false;
|
||||
_mockTxnMgr.NestedTransactionsAllowed = true;
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.AreEqual( _mockTxnMgr.Transaction, status.Transaction );
|
||||
Assert.IsTrue( !status.IsNewTransaction );
|
||||
Assert.IsTrue( status.NewSynchronization );
|
||||
Assert.IsTrue( status.ReadOnly );
|
||||
Assert.IsNull( status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void DefaultPropagationBehaviorWithNullDefinition()
|
||||
{
|
||||
setGeneralGetTransactionExpectations();
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.AreEqual(_mockTxnMgr.Transaction, status.Transaction);
|
||||
Assert.IsTrue(status.IsNewTransaction);
|
||||
Assert.AreEqual(true, status.NewSynchronization);
|
||||
Assert.IsTrue(!status.ReadOnly);
|
||||
Assert.IsNull(status.SuspendedResources);
|
||||
}
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(null);
|
||||
Assert.AreEqual( _mockTxnMgr.Transaction, status.Transaction );
|
||||
Assert.IsTrue( !status.IsNewTransaction );
|
||||
Assert.IsTrue( status.NewSynchronization );
|
||||
Assert.IsTrue( !status.ReadOnly );
|
||||
Assert.IsNull( status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void DefaultNoExistingTransaction()
|
||||
{
|
||||
setVanillaGetTransactionExpectations();
|
||||
_mockTxnMgr.SetExpectedCalls( "DoBegin", 1 );
|
||||
[Test]
|
||||
public void NestedTransactionWithSavepoint()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Nested;
|
||||
def.ReadOnly = false;
|
||||
setVanillaGetTransactionExpectations();
|
||||
_mockTxnMgr.SetTransaction(new MyMockTxnObjectSavepointMgr());
|
||||
_mockTxnMgr.SetExpectedCalls("DoBegin", 0);
|
||||
_mockTxnMgr.Savepoints = true;
|
||||
_mockTxnMgr.NestedTransactionsAllowed = true;
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(null);
|
||||
Assert.IsNotNull( status.Transaction );
|
||||
Assert.IsTrue( status.IsNewTransaction );
|
||||
Assert.IsTrue( status.NewSynchronization );
|
||||
Assert.IsTrue( !status.ReadOnly );
|
||||
Assert.IsNull( status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void DefaultBehaviorDefaultPropagationNoExistingTransaction()
|
||||
{
|
||||
setVanillaGetTransactionExpectations();
|
||||
_mockTxnMgr.SetExpectedCalls( "DoBegin", 0 );
|
||||
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Never;
|
||||
def.ReadOnly = true;
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.AreEqual(_mockTxnMgr.Transaction, status.Transaction);
|
||||
Assert.IsFalse(status.IsNewTransaction);
|
||||
Assert.IsFalse(status.NewSynchronization);
|
||||
Assert.IsTrue(!status.ReadOnly);
|
||||
Assert.IsNull(status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void DefaultPropagationBehavior()
|
||||
{
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Required;
|
||||
def.ReadOnly = true;
|
||||
setGeneralGetTransactionExpectations();
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.IsNull( status.Transaction );
|
||||
Assert.IsTrue( !status.IsNewTransaction );
|
||||
Assert.IsTrue( status.NewSynchronization );
|
||||
Assert.IsTrue( status.ReadOnly );
|
||||
Assert.IsNull( status.SuspendedResources);
|
||||
}
|
||||
private void setGeneralGetTransactionExpectations()
|
||||
{
|
||||
_mockTxnMgr.SetTransaction( new object() );
|
||||
setVanillaGetTransactionExpectations();
|
||||
}
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.AreEqual(_mockTxnMgr.Transaction, status.Transaction);
|
||||
Assert.IsTrue(!status.IsNewTransaction);
|
||||
Assert.IsTrue(status.NewSynchronization);
|
||||
Assert.IsTrue(status.ReadOnly);
|
||||
Assert.IsNull(status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void DefaultPropagationBehaviorWithNullDefinition()
|
||||
{
|
||||
setGeneralGetTransactionExpectations();
|
||||
|
||||
private void setVanillaGetTransactionExpectations()
|
||||
{
|
||||
_mockTxnMgr.SetExpectedCalls( "DoGetTransaction", 1);
|
||||
_mockTxnMgr.SetExpectedCalls( "IsExistingTransaction", 1);
|
||||
}
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(null);
|
||||
Assert.AreEqual(_mockTxnMgr.Transaction, status.Transaction);
|
||||
Assert.IsFalse(status.IsNewTransaction);
|
||||
Assert.IsTrue(status.NewSynchronization);
|
||||
Assert.IsFalse(status.ReadOnly);
|
||||
Assert.IsNull(status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void DefaultNoExistingTransaction()
|
||||
{
|
||||
setVanillaGetTransactionExpectations();
|
||||
_mockTxnMgr.SetExpectedCalls("DoBegin", 1);
|
||||
|
||||
}
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(null);
|
||||
Assert.IsNotNull(status.Transaction);
|
||||
Assert.IsTrue(status.IsNewTransaction);
|
||||
Assert.IsTrue(status.NewSynchronization);
|
||||
Assert.IsTrue(!status.ReadOnly);
|
||||
Assert.IsNull(status.SuspendedResources);
|
||||
}
|
||||
[Test]
|
||||
public void DefaultBehaviorDefaultPropagationNoExistingTransaction()
|
||||
{
|
||||
setVanillaGetTransactionExpectations();
|
||||
_mockTxnMgr.SetExpectedCalls("DoBegin", 0);
|
||||
|
||||
MockTxnDefinition def = new MockTxnDefinition();
|
||||
def.PropagationBehavior = TransactionPropagation.Never;
|
||||
def.ReadOnly = true;
|
||||
|
||||
DefaultTransactionStatus status = (DefaultTransactionStatus)_mockTxnMgr.GetTransaction(def);
|
||||
Assert.IsNull(status.Transaction);
|
||||
Assert.IsTrue(!status.IsNewTransaction);
|
||||
Assert.IsTrue(status.NewSynchronization);
|
||||
Assert.IsTrue(status.ReadOnly);
|
||||
Assert.IsNull(status.SuspendedResources);
|
||||
}
|
||||
private void setGeneralGetTransactionExpectations()
|
||||
{
|
||||
_mockTxnMgr.SetTransaction(new object());
|
||||
setVanillaGetTransactionExpectations();
|
||||
}
|
||||
|
||||
private void setVanillaGetTransactionExpectations()
|
||||
{
|
||||
_mockTxnMgr.SetExpectedCalls("DoGetTransaction", 1);
|
||||
_mockTxnMgr.SetExpectedCalls("IsExistingTransaction", 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user