diff --git a/src/Spring/Spring.Data.NHibernate21/Data/NHibernate/HibernateTxScopeTransactionManager.cs b/src/Spring/Spring.Data.NHibernate21/Data/NHibernate/HibernateTxScopeTransactionManager.cs
index eea02dd9..56da95b9 100644
--- a/src/Spring/Spring.Data.NHibernate21/Data/NHibernate/HibernateTxScopeTransactionManager.cs
+++ b/src/Spring/Spring.Data.NHibernate21/Data/NHibernate/HibernateTxScopeTransactionManager.cs
@@ -977,7 +977,10 @@ namespace Spring.Data.NHibernate
public void SetRollbackOnly()
{
- SessionHolder.RollbackOnly = true;
+ if (SessionHolder != null)
+ {
+ SessionHolder.RollbackOnly = true;
+ }
if (ConnectionHolder != null)
{
ConnectionHolder.RollbackOnly = true;
@@ -993,8 +996,8 @@ namespace Spring.Data.NHibernate
{
get
{
- return SessionHolder.RollbackOnly ||
- (ConnectionHolder != null && ConnectionHolder.RollbackOnly);
+ return ((SessionHolder != null && SessionHolder.RollbackOnly) ||
+ (ConnectionHolder != null && ConnectionHolder.RollbackOnly));
}
}
}
diff --git a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.cs b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.cs
index 7b963665..31d2ef78 100644
--- a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.cs
+++ b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.cs
@@ -34,6 +34,7 @@ using Spring.Transaction;
using Spring.Transaction.Support;
using Spring.Transaction.Interceptor;
using System.Transactions;
+using System.Collections.Generic;
#endregion
@@ -46,26 +47,46 @@ namespace Spring.Data.NHibernate
[TestFixture]
public class HibernateTxScopeTransactionManagerTests
{
- #region Fields
- private IDbProvider dbProvider;
-
- private IPlatformTransactionManager transactionManager;
-
- private IApplicationContext ctx;
- #endregion
-
- #region Constants
-
///
/// The shared instance for this class (and derived classes).
///
protected static readonly ILog log =
- LogManager.GetLogger(typeof(TemplateTests));
+ LogManager.GetLogger(typeof(HibernateTxScopeTransactionManagerTests));
- //// force Spring.Data.NHibernate to be preloaded by runtime
- //private Type TLocalSessionFactoryObject = typeof(LocalSessionFactoryObject);
+ private IApplicationContext ctx;
- #endregion
+ private IDbProvider dbProvider;
+
+ private IPlatformTransactionManager transactionManager;
+
+ [Test]
+ public void CanProperlyReleaseConnectionsWhenTransactionsAreRolledBack()
+ {
+ for (int i = 0; i < 200; i++)
+ {
+ try
+ {
+ DoSave(true);
+ }
+ catch (Exception)
+ {
+ }
+ }
+ }
+
+ [Test]
+ [Ignore("Test harness left in place to demonstrate the leaking connection issue present in NH2.1 and later")]
+ public void DoesNotLeakConnection()
+ {
+ DoPreventConnectionLeaksPreventionPattern();
+ }
+
+ [Test]
+ [Ignore("Test harness left in place to demonstrate the leaking connection issue present in NH2.1 and later")]
+ public void LeaksConnection()
+ {
+ DoConnectionLeakingAntiPattern();
+ }
[SetUp]
public void SetUp()
@@ -92,14 +113,66 @@ namespace Spring.Data.NHibernate
}
}
- private static void ExecuteSql(IDbConnection conn, string sql)
+ ///
+ /// this method will fail the test as it follows the anti-pattern of failing to use the (mandatory) NH Transaction to wrap the session call
+ ///
+ private void DoConnectionLeakingAntiPattern()
{
- IDbCommand cmd;
- cmd = conn.CreateCommand();
- cmd.CommandText = sql;
- cmd.ExecuteNonQuery();
+ //this counter must be larger than the 'Max Pool Size' setting in the connection string for this test to demonstrate the issue
+ int counter = 200;
+
+ for (int i = 0; i < counter; i++)
+ {
+
+ using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
+ {
+ using (ISession session = ((ISessionFactory)ctx["SessionFactory"]).OpenSession())
+ {
+ IList to = session.CreateCriteria().List();
+ }
+
+ //because scope.Complete() is never called, the Transaction is rolled back and this results in the orpahned connections
+ }
+
+ }
+
}
+ ///
+ /// this method demonstrates the proper pattern to follow w NH 2.1 and later, mandating the use of an NH transaction wrapping the session
+ ///
+ private void DoPreventConnectionLeaksPreventionPattern()
+ {
+ //this counter must be larger than the 'Max Pool Size' setting in the connection string for this test to demonstrate the issue
+ int counter = 200;
+
+ for (int i = 0; i < counter; i++)
+ {
+
+ using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
+ {
+ using (ISession session = ((ISessionFactory)ctx["SessionFactory"]).OpenSession())
+ {
+ using (ITransaction tx = session.BeginTransaction())
+ {
+ try
+ {
+ IList to = session.CreateCriteria().List();
+ throw new Exception("this exception simulates something going wrong!");
+
+ }
+ catch (Exception)
+ {
+ tx.Rollback();
+ }
+ }
+ }
+
+ //because scope.Complete() is never called, the Transaction is rolled back but the presence of the NH transaction and its
+ // associated Rollback() call will enable NH to properly release the connection
+ }
+ }
+ }
[Transaction]
private void DoSave(bool simulateException)
@@ -118,22 +191,16 @@ namespace Spring.Data.NHibernate
tx.Complete();
}
-
+
}
- [Test]
- public void CanProperlyReleaseConnectionsWhenTransactionsAreRolledBack()
+ private static void ExecuteSql(IDbConnection conn, string sql)
{
- for (int i = 0; i < 200; i++)
- {
- try
- {
- DoSave(true);
- }
- catch (Exception)
- {
- }
- }
+ IDbCommand cmd;
+ cmd = conn.CreateCommand();
+ cmd.CommandText = sql;
+ cmd.ExecuteNonQuery();
}
+
}
}
diff --git a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.xml b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.xml
index 8e82d88f..a9392ddb 100644
--- a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.xml
+++ b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Data/NHibernate/HibernateTxScopeTransactionManagerTests.xml
@@ -3,13 +3,12 @@
xmlns:db="http://www.springframework.net/database"
xmlns:tx="http://www.springframework.net/tx">
-
+
-
-
-
-
-
-
-
-
diff --git a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate21.Integration.Tests.2010.csproj b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate21.Integration.Tests.2010.csproj
index 1b157903..5eb83fa7 100644
--- a/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate21.Integration.Tests.2010.csproj
+++ b/test/Spring/Spring.Data.NHibernate21.Integration.Tests/Spring.Data.NHibernate21.Integration.Tests.2010.csproj
@@ -25,6 +25,7 @@
TRACE;DEBUG;NET_2_0,NH_2_0,NH_2_1
prompt
4
+ true
pdbonly