You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by gb...@apache.org on 2005/08/13 21:00:56 UTC

svn commit: r232516 - in /ibatis/trunk/cs/mapper: IBatisNet.DataAccess.Test/NUnit/DaoTests/ IBatisNet.DataAccess/ IBatisNet.DataAccess/DaoSessionHandlers/ IBatisNet.DataMapper.Test/NUnit/SqlMapTests/ IBatisNet.DataMapper/

Author: gbayon
Date: Sat Aug 13 12:00:42 2005
New Revision: 232516

URL: http://svn.apache.org/viewcvs?rev=232516&view=rev
Log:
- Fixed IBATISNET-102 Calling DaoManager in different threads causes an Exception

Added:
    ibatis/trunk/cs/mapper/IBatisNet.DataAccess/SessionHolder.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SessionHolder.cs
Modified:
    ibatis/trunk/cs/mapper/IBatisNet.DataAccess.Test/NUnit/DaoTests/BaseDaoTest.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoManager.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoSessionHandlers/SqlMapDaoSession.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataAccess/IBatisNet.DataAccess.csproj
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/ThreadTest.cs
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/IBatisNet.DataMapper.csproj
    ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SqlMapper.cs

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataAccess.Test/NUnit/DaoTests/BaseDaoTest.cs
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataAccess.Test/NUnit/DaoTests/BaseDaoTest.cs?rev=232516&r1=232515&r2=232516&view=diff
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataAccess.Test/NUnit/DaoTests/BaseDaoTest.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataAccess.Test/NUnit/DaoTests/BaseDaoTest.cs Sat Aug 13 12:00:42 2005
@@ -1,17 +1,13 @@
+// DataSource definition
+	// ScriptRunner definition
 using System;
+using System.Configuration;
 using System.IO;
 using System.Threading;
-using System.Configuration;
-
-using IBatisNet.DataAccess;
-using IBatisNet.Common; // DataSource definition
-using IBatisNet.Common.Utilities; // ScriptRunner definition
-
+using IBatisNet.Common;
+using IBatisNet.Common.Utilities;
 using IBatisNet.DataAccess.Test.Dao.Interfaces;
-
-using IBatisNet.DataAccess.Test.NUnit;
 using IBatisNet.DataAccess.Test.Domain;
-
 using NUnit.Framework;
 
 namespace IBatisNet.DataAccess.Test.NUnit.DaoTests
@@ -19,28 +15,28 @@
 	/// <summary>
 	/// Summary description for BaseDaoTest.
 	/// </summary>
-	[TestFixture] 
+	[TestFixture]
 	public abstract class BaseDaoTest
 	{
 		/// <summary>
 		/// A daoManager
 		/// </summary>
-		protected static  DaoManager daoManager = null;
+		protected static DaoManager daoManager = null;
+
 		protected static string ScriptDirectory = null;
 
+		private ManualResetEvent _startEvent = new ManualResetEvent(false);
+		private ManualResetEvent _stopEvent = new ManualResetEvent(false);
+
 		/// <summary>
 		/// Constructor
 		/// </summary>
 		static BaseDaoTest()
 		{
-	
-			ScriptDirectory = Path.Combine( Path.Combine( Path.Combine( Path.Combine(Resources.ApplicationBase, ".."), ".."), "Scripts"), ConfigurationSettings.AppSettings["database"]) + Path.DirectorySeparatorChar;
-				
-//				Resources.RootDirectory + Path.DirectorySeparatorChar +
-//				"Scripts" + Path.DirectorySeparatorChar +
-//				ConfigurationSettings.AppSettings["database"]+ Path.DirectorySeparatorChar;
+			ScriptDirectory = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Resources.ApplicationBase, ".."), ".."), "Scripts"), ConfigurationSettings.AppSettings["database"]) + Path.DirectorySeparatorChar;
 		}
 
+
 		/// <summary>
 		/// Run a sql batch for the datasource.
 		/// </summary>
@@ -59,12 +55,12 @@
 		/// Verify that DaoManager.GetDao("Account")
 		/// return an object that implemetent the interface IAccountDao.
 		/// </summary>
-		[Test] 						
+		[Test]
 		public void TestGetDao()
 		{
-			Type type = typeof(IAccountDao);
+			Type type = typeof (IAccountDao);
 
-			IAccountDao accountDao = (IAccountDao)daoManager[typeof(IAccountDao)];
+			IAccountDao accountDao = (IAccountDao) daoManager[typeof (IAccountDao)];
 
 			Assert.IsNotNull(accountDao);
 			Assert.IsTrue(type.IsInstanceOfType(accountDao));
@@ -74,10 +70,10 @@
 		/// <summary>
 		/// Test CreateAccount
 		/// </summary>
-		[Test] 
-		public void TestCreateAccount () 
+		[Test]
+		public void TestCreateAccount()
 		{
-			IAccountDao accountDao = (IAccountDao)daoManager[typeof(IAccountDao)];
+			IAccountDao accountDao = (IAccountDao) daoManager[typeof (IAccountDao)];
 
 			Account account = NewAccount();
 
@@ -88,10 +84,10 @@
 
 				account = accountDao.GetAccountById(1001);
 			}
-			catch(Exception e)
+			catch (Exception e)
 			{
 				// Ignore
-				Console.WriteLine("TestCreateAccount, error cause : "+e.Message);
+				Console.WriteLine("TestCreateAccount, error cause : " + e.Message);
 			}
 			finally
 			{
@@ -105,10 +101,10 @@
 		/// <summary>
 		/// Test CreateAccount
 		/// </summary>
-		[Test] 
-		public void TestCreateAccountExplicitOpenSession () 
+		[Test]
+		public void TestCreateAccountExplicitOpenSession()
 		{
-			IAccountDao accountDao = daoManager[typeof(IAccountDao)] as IAccountDao;
+			IAccountDao accountDao = daoManager[typeof (IAccountDao)] as IAccountDao;
 
 			Account account = NewAccount();
 
@@ -118,10 +114,10 @@
 
 				account = accountDao.GetAccountById(1001);
 			}
-			catch(Exception e)
+			catch (Exception e)
 			{
 				// Ignore
-				Console.WriteLine("TestCreateAccount, error cause : "+e.Message);
+				Console.WriteLine("TestCreateAccount, error cause : " + e.Message);
 			}
 			finally
 			{
@@ -134,10 +130,10 @@
 		/// <summary>
 		/// Test Transaction Rollback
 		/// </summary>
-		[Test] 
-		public void TestTransactionRollback () 
+		[Test]
+		public void TestTransactionRollback()
 		{
-			IAccountDao accountDao = (IAccountDao)daoManager[typeof(IAccountDao)];
+			IAccountDao accountDao = (IAccountDao) daoManager[typeof (IAccountDao)];
 
 			Account account = NewAccount();
 			daoManager.OpenConnection();
@@ -146,7 +142,7 @@
 
 			account2.EmailAddress = "someotherAddress@somewhere.com";
 
-			try 
+			try
 			{
 				daoManager.BeginTransaction();
 
@@ -155,12 +151,12 @@
 				throw new Exception("BOOM!");
 
 				//daoManager.CommitTransaction();
-			} 
+			}
 			catch
 			{
 				daoManager.RollBackTransaction();
-			} 
-			finally 
+			}
+			finally
 			{
 			}
 
@@ -177,10 +173,10 @@
 		/// <summary>
 		/// Test Transaction Commit
 		/// </summary>
-		[Test] 
-		public void TestTransactionCommit () 
+		[Test]
+		public void TestTransactionCommit()
 		{
-			IAccountDao accountDao = (IAccountDao)daoManager[typeof(IAccountDao)];
+			IAccountDao accountDao = (IAccountDao) daoManager[typeof (IAccountDao)];
 
 			Account account = NewAccount();
 
@@ -190,14 +186,14 @@
 
 			account2.EmailAddress = "someotherAddress@somewhere.com";
 
-			try 
+			try
 			{
 				daoManager.BeginTransaction();
 				accountDao.Create(account);
 				accountDao.Update(account2);
 				daoManager.CommitTransaction();
-			} 
-			finally 
+			}
+			finally
 			{
 				// Nothing
 			}
@@ -214,10 +210,10 @@
 		/// <summary>
 		/// Test Delete
 		/// </summary>
-		[Test] 
-		public void TestDeleteAccount () 
+		[Test]
+		public void TestDeleteAccount()
 		{
-			IAccountDao accountDao = (IAccountDao)daoManager[typeof(IAccountDao)];
+			IAccountDao accountDao = (IAccountDao) daoManager[typeof (IAccountDao)];
 
 			Account account = NewAccount();
 
@@ -225,7 +221,7 @@
 
 			accountDao.Create(account);
 			account = accountDao.GetAccountById(1001);
-			
+
 			Assert.IsNotNull(account);
 			Assert.AreEqual("Calamity.Jane@somewhere.com", account.EmailAddress);
 
@@ -240,27 +236,27 @@
 		/// <summary>
 		/// Test Using syntax on daoManager.OpenConnection
 		/// </summary>
-		[Test] 
-		public void TestUsingConnection() 
+		[Test]
+		public void TestUsingConnection()
 		{
-			IAccountDao accountDao = (IAccountDao)daoManager[typeof(IAccountDao)];
+			IAccountDao accountDao = (IAccountDao) daoManager[typeof (IAccountDao)];
 
-			using ( IDalSession session = daoManager.OpenConnection() )
+			using (IDalSession session = daoManager.OpenConnection())
 			{
 				Account account = NewAccount();
 				accountDao.Create(account);
-			}   // compiler will call Dispose on DaoSession
+			} // compiler will call Dispose on DaoSession
 		}
 
 		/// <summary>
 		/// Test Test Using syntax on daoManager.BeginTransaction
 		/// </summary>
-		[Test] 
-		public void TestUsingTransaction() 
+		[Test]
+		public void TestUsingTransaction()
 		{
-			IAccountDao accountDao = (IAccountDao)daoManager[typeof(IAccountDao)];
+			IAccountDao accountDao = (IAccountDao) daoManager[typeof (IAccountDao)];
 
-			using ( IDalSession session = daoManager.BeginTransaction() )
+			using (IDalSession session = daoManager.BeginTransaction())
 			{
 				Account account = NewAccount();
 				Account account2 = accountDao.GetAccountById(1);
@@ -275,11 +271,55 @@
 
 		#endregion
 
+		#region Thread test
+
+		[Test]
+		public void TestCommonUsageMultiThread()
+		{
+			const int threadCount = 10;
+
+			Thread[] threads = new Thread[threadCount];
+
+			for (int i = 0; i < threadCount; i++)
+			{
+				threads[i] = new Thread(new ThreadStart(ExecuteMethodUntilSignal));
+				threads[i].Start();
+			}
+
+			_startEvent.Set();
+
+			Thread.CurrentThread.Join(1*2000);
+
+			_stopEvent.Set();
+		}
+
+		public void ExecuteMethodUntilSignal()
+		{
+			_startEvent.WaitOne(int.MaxValue, false);
+
+			IAccountDao accountDao = daoManager[typeof (IAccountDao)] as IAccountDao;
+
+			while (!_stopEvent.WaitOne(1, false))
+			{
+				Assert.IsFalse(daoManager.IsDaoSessionStarted());
+
+				Account account = account = accountDao.GetAccountById(1);
+
+				Assert.IsFalse(daoManager.IsDaoSessionStarted());
+
+				Assert.AreEqual(1, account.Id, "account.Id");
+				Assert.AreEqual("Joe", account.FirstName, "account.FirstName");
+				Assert.AreEqual("Dalton", account.LastName, "account.LastName");
+			}
+		}
+
+		#endregion
+
 		/// <summary>
 		/// Create a new account with id = 1001
 		/// </summary>
 		/// <returns>An account</returns>
-		protected Account NewAccount() 
+		protected Account NewAccount()
 		{
 			Account account = new Account();
 			account.Id = 1001;

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoManager.cs
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoManager.cs?rev=232516&r1=232515&r2=232516&view=diff
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoManager.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoManager.cs Sat Aug 13 12:00:42 2005
@@ -32,12 +32,10 @@
 using System.Threading;
 using System.Xml;
 using IBatisNet.Common;
-using IBatisNet.Common.Exceptions;
 using IBatisNet.Common.Utilities;
 using IBatisNet.DataAccess.Configuration;
 using IBatisNet.DataAccess.Exceptions;
 using IBatisNet.DataAccess.Interfaces;
-using IBatisNet.DataAccess.SessionContainer;
 
 #endregion
 
@@ -123,7 +121,7 @@
 		/// <summary>
 		/// Container session unique for each thread. 
 		/// </summary>
-		private ISessionContainer _sessionContainer = null;
+		private SessionHolder _sessionHolder = null;
 		#endregion
 
 		#region Properties
@@ -197,11 +195,11 @@
 		{
 			get 
 			{ 
-				if (_sessionContainer.LocalSession == null) 
+				if (_sessionHolder.LocalSession == null) 
 				{
 					throw new DataAccessException("DaoManager could not invoke LocalDaoSession. No DaoSession was started. Call OpenConnection() or BeginTransaction first.");
 				}
-				return _sessionContainer.LocalSession;
+				return _sessionHolder.LocalSession;
 			}
 		}
 
@@ -214,7 +212,7 @@
 		/// </summary>
 		private DaoManager() 
 		{ 
-			_sessionContainer = SessionContainerFactory.GetSessionContainer(this.Name);
+			_sessionHolder = new SessionHolder(this.Name);
 		}
 		#endregion
 
@@ -390,7 +388,7 @@
 		/// <returns>True or False</returns>
 		public bool IsDaoSessionStarted()
 		{
-			return (_sessionContainer.LocalSession != null);
+			return (_sessionHolder.LocalSession != null);
 		}
 
 		/// <summary>
@@ -403,12 +401,12 @@
 			{
 				throw new DataAccessException("DaoManager could not get DaoSession.  DaoSessionPool was null (possibly not configured).");
 			}
-			if (_sessionContainer.LocalSession != null) 
+			if (_sessionHolder.LocalSession != null) 
 			{
 				throw new DataAccessException("DaoManager could not invoke OpenConnection(). A connection is already started. Call CloseConnection first.");
 			}
 			IDalSession session = _daoSessionHandler.GetDaoSession(this);
-			_sessionContainer.Store(session);
+			_sessionHolder.Store(session);
 			session.OpenConnection();
 			return session;
 		}
@@ -418,13 +416,13 @@
 		/// </summary>
 		public void CloseConnection()
 		{
-			if (_sessionContainer.LocalSession == null) 
+			if (_sessionHolder.LocalSession == null) 
 			{
 				throw new DataAccessException("DaoManager could not invoke CloseConnection(). No connection was started. Call OpenConnection() first.");
 			}
 			try
 			{
-				IDalSession session = _sessionContainer.LocalSession;
+				IDalSession session = _sessionHolder.LocalSession;
 				session.CloseConnection();	
 			} 
 			catch(Exception ex)
@@ -433,7 +431,7 @@
 			}
 			finally 
 			{
-				_sessionContainer.Dispose();
+				_sessionHolder.Dispose();
 			}
 		}
 
@@ -447,12 +445,12 @@
 			{
 				throw new DataAccessException("DaoManager could not get DaoSession.  DaoSessionPool was null (possibly not configured).");
 			}
-			if (_sessionContainer.LocalSession != null) 
+			if (_sessionHolder.LocalSession != null) 
 			{
 				throw new DataAccessException("DaoManager could not invoke BeginTransaction(). A DaoSession is already started. Call CommitTransaction() or RollbackTransaction first.");
 			}
 			IDalSession session = _daoSessionHandler.GetDaoSession(this);
-			_sessionContainer.Store(session);
+			_sessionHolder.Store(session);
 			session.BeginTransaction();
 			return session;
 		}
@@ -470,13 +468,13 @@
 			{
 				throw new DataAccessException("DaoManager could not get DaoSession.  DaoSessionPool was null (possibly not configured).");
 			}
-			if (_sessionContainer.LocalSession != null) 
+			if (_sessionHolder.LocalSession != null) 
 			{
 				throw new DataAccessException("DaoManager could not invoke BeginTransaction(). A DaoSession is already started. Call CommitTransaction() or RollbackTransaction first.");
 			}
 
 			IDalSession session = _daoSessionHandler.GetDaoSession(this);
-			_sessionContainer.Store(session);
+			_sessionHolder.Store(session);
 			session.BeginTransaction(isolationLevel);
 			return session;
 		}
@@ -489,18 +487,18 @@
 		/// </remarks>
 		public void CommitTransaction()
 		{
-			if (_sessionContainer.LocalSession == null) 
+			if (_sessionHolder.LocalSession == null) 
 			{
 				throw new DataAccessException("DaoManager could not invoke CommitTransaction(). No Transaction was started. Call BeginTransaction() first.");
 			}
 			try
 			{
-				IDalSession session = _sessionContainer.LocalSession;
+				IDalSession session = _sessionHolder.LocalSession;
 				session.CommitTransaction();
 			} 
 			finally 
 			{
-				_sessionContainer.Dispose();
+				_sessionHolder.Dispose();
 			}
 		}
 
@@ -512,19 +510,28 @@
 		/// </remarks>
 		public void RollBackTransaction()
 		{
-			if (_sessionContainer.LocalSession == null) 
+			if (_sessionHolder.LocalSession == null) 
 			{
 				throw new DataAccessException("DaoManager could not invoke RollBackTransaction(). No Transaction was started. Call BeginTransaction() first.");
 			}
 			try
 			{
-				IDalSession session = _sessionContainer.LocalSession;
+				IDalSession session = _sessionHolder.LocalSession;
 				session.RollBackTransaction();	
 			} 
 			finally 
 			{
-				_sessionContainer.Dispose();
+				_sessionHolder.Dispose();
 			}
+		}
+
+		/// <summary>
+		/// Release the local session.
+		/// </summary>
+		/// <remarks>Use in SqlMapDaoSession</remarks>
+		internal void Dispose()
+		{
+			_sessionHolder.Dispose();
 		}
 
 		#endregion

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoSessionHandlers/SqlMapDaoSession.cs
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoSessionHandlers/SqlMapDaoSession.cs?rev=232516&r1=232515&r2=232516&view=diff
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoSessionHandlers/SqlMapDaoSession.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataAccess/DaoSessionHandlers/SqlMapDaoSession.cs Sat Aug 13 12:00:42 2005
@@ -244,6 +244,7 @@
 		public override void Dispose()
 		{
 			_sqlMap.LocalSession.Dispose();
+			daoManager.Dispose();
 		}
 		#endregion
 

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataAccess/IBatisNet.DataAccess.csproj
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataAccess/IBatisNet.DataAccess.csproj?rev=232516&r1=232515&r2=232516&view=diff
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataAccess/IBatisNet.DataAccess.csproj (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataAccess/IBatisNet.DataAccess.csproj Sat Aug 13 12:00:42 2005
@@ -148,6 +148,11 @@
                     BuildAction = "Content"
                 />
                 <File
+                    RelPath = "SessionHolder.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "Configuration\Dao.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
@@ -219,26 +224,6 @@
                 />
                 <File
                     RelPath = "Scope\ErrorContext.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
-                    RelPath = "SessionContainer\ISessionContainer.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
-                    RelPath = "SessionContainer\SessionContainerFactory.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
-                    RelPath = "SessionContainer\WebSessionContainer.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
-                    RelPath = "SessionContainer\WindowSessionContainer.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />

Added: ibatis/trunk/cs/mapper/IBatisNet.DataAccess/SessionHolder.cs
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataAccess/SessionHolder.cs?rev=232516&view=auto
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataAccess/SessionHolder.cs (added)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataAccess/SessionHolder.cs Sat Aug 13 12:00:42 2005
@@ -0,0 +1,109 @@
+
+#region Apache Notice
+/*****************************************************************************
+ * $Header: $
+ * $Revision: $
+ * $Date: $
+ * 
+ * iBATIS.NET Data Mapper
+ * Copyright (C) 2004 - Gilles Bayon
+ *  
+ * 
+ * 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
+
+#region Using
+
+using System.Runtime.Remoting.Messaging;
+using IBatisNet.Common;
+
+#endregion
+
+namespace IBatisNet.DataAccess
+{
+	/// <summary>
+	/// Summary description for SessionHolder.
+	/// </summary>
+	/// <remarks>
+	/// See also LocalDataStoreSlot
+	/// </remarks>
+	public class SessionHolder
+	{
+		#region Constants
+
+		/// <summary>
+		/// Token for SqlMapConfig xml root.
+		/// </summary>
+		private const string LOCAL_SESSION = "_IBATIS_LOCAL_DAOSESSION_";
+
+		#endregion
+
+		#region Fields
+		private string _sessionName = string.Empty;
+		#endregion
+
+		#region Constructor (s) / Destructor
+
+		/// <summary>
+		/// Constructor
+		/// </summary>
+		/// <param name="daoManagerName">The DaoManager name.</param>
+		public SessionHolder(string daoManagerName)
+		{
+			_sessionName = LOCAL_SESSION + daoManagerName;
+		}
+		#endregion
+
+
+		#region ISessionContainer Members
+
+		#region Properties
+		/// <summary>
+		/// Get the local session
+		/// </summary>
+		public IDalSession LocalSession
+		{
+			get
+			{
+				return CallContext.GetData(_sessionName) as IDalSession;
+			}
+		}
+		#endregion
+
+		#region Methods
+		/// <summary>
+		/// Store the local session.
+		/// Ensure that the session is unique for each thread.
+		/// </summary>
+		/// <param name="session">The session to store</param>
+		public void Store(IDalSession session)
+		{
+			CallContext.SetData(_sessionName, session);
+		}
+
+		/// <summary>
+		/// Remove the local session.
+		/// </summary>
+		public void Dispose()
+		{
+			CallContext.SetData(_sessionName, null);
+		}
+
+		#endregion
+
+		#endregion
+
+	}
+}

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/ThreadTest.cs
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/ThreadTest.cs?rev=232516&r1=232515&r2=232516&view=diff
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/ThreadTest.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper.Test/NUnit/SqlMapTests/ThreadTest.cs Sat Aug 13 12:00:42 2005
@@ -23,6 +23,8 @@
 		private static readonly ILog _logger = LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );
 
 		private static int _numberOfThreads = 10;
+		private ManualResetEvent  _startEvent = new ManualResetEvent(false);
+		private ManualResetEvent  _stopEvent = new ManualResetEvent(false);
 
 		#region SetUp & TearDown
 
@@ -45,6 +47,44 @@
 		#endregion
 
 		#region Thread test
+
+		[Test]
+		public void TestCommonUsageMultiThread()
+		{
+			const int threadCount = 10;
+
+			Thread[] threads = new Thread[threadCount];
+			
+			for(int i = 0; i < threadCount; i++)
+			{
+				threads[i] = new Thread(new ThreadStart(ExecuteMethodUntilSignal));
+				threads[i].Start();
+			}
+
+			_startEvent.Set();
+
+			Thread.CurrentThread.Join(1 * 2000);
+
+			_stopEvent.Set();
+		}
+
+		public void ExecuteMethodUntilSignal()
+		{
+			_startEvent.WaitOne(int.MaxValue, false);
+
+			while (!_stopEvent.WaitOne(1, false))
+			{
+				Assert.IsFalse(sqlMap.IsSessionStarted);
+
+				Account account = (Account) sqlMap.QueryForObject("GetAccountViaColumnIndex", 1);
+				
+				Assert.IsFalse(sqlMap.IsSessionStarted);
+				
+				Assert.AreEqual(1, account.Id, "account.Id");
+				Assert.AreEqual("Joe", account.FirstName, "account.FirstName");
+				Assert.AreEqual("Dalton", account.LastName, "account.LastName");
+			}
+		}
 
 		/// <summary>
 		/// Test BeginTransaction, CommitTransaction

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/IBatisNet.DataMapper.csproj
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/IBatisNet.DataMapper.csproj?rev=232516&r1=232515&r2=232516&view=diff
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/IBatisNet.DataMapper.csproj (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/IBatisNet.DataMapper.csproj Sat Aug 13 12:00:42 2005
@@ -153,6 +153,11 @@
                     BuildAction = "Content"
                 />
                 <File
+                    RelPath = "SessionHolder.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "SqlMap.xsd"
                     BuildAction = "EmbeddedResource"
                 />
@@ -802,26 +807,6 @@
                 />
                 <File
                     RelPath = "Scope\RequestScope.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
-                    RelPath = "SessionContainer\ISessionContainer.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
-                    RelPath = "SessionContainer\SessionContainerFactory.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
-                    RelPath = "SessionContainer\WebSessionContainer.cs"
-                    SubType = "Code"
-                    BuildAction = "Compile"
-                />
-                <File
-                    RelPath = "SessionContainer\WindowSessionContainer.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />

Added: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SessionHolder.cs
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SessionHolder.cs?rev=232516&view=auto
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SessionHolder.cs (added)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SessionHolder.cs Sat Aug 13 12:00:42 2005
@@ -0,0 +1,106 @@
+
+#region Apache Notice
+/*****************************************************************************
+ * $Header: $
+ * $Revision: $
+ * $Date: $
+ * 
+ * iBATIS.NET Data Mapper
+ * Copyright (C) 2004 - Gilles Bayon
+ *  
+ * 
+ * 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
+
+#region Using
+
+using System.Runtime.Remoting.Messaging;
+
+#endregion
+
+namespace IBatisNet.DataMapper
+{
+	/// <summary>
+	/// Summary description for SessionHolder.
+	/// </summary>
+	/// <remarks>
+	/// See also LocalDataStoreSlot
+	/// </remarks>
+	public class SessionHolder
+	{
+		#region Constants
+
+		/// <summary>
+		/// Token for SqlMapConfig xml root.
+		/// </summary>
+		private const string LOCAL_SESSION = "_IBATIS_LOCAL_SQLMAP_SESSION_";
+
+		#endregion
+
+		#region Fields
+		private string _sessionName = string.Empty;
+		#endregion
+
+		#region Constructor (s) / Destructor
+
+		/// <summary>
+		/// Constructor
+		/// </summary>
+		/// <param name="sqlMapperId">SqlMapper identifiant</param>
+		public SessionHolder(string sqlMapperId)
+		{
+			_sessionName = LOCAL_SESSION + sqlMapperId;
+		}
+		#endregion
+
+		#region ISessionContainer Members
+
+		#region Properties
+		/// <summary>
+		/// Get the local session
+		/// </summary>
+		public SqlMapSession LocalSession
+		{
+			get
+			{
+				return CallContext.GetData(_sessionName) as SqlMapSession;
+			}
+		}
+		#endregion
+
+		#region Methods
+		/// <summary>
+		/// Store the local session on the container.
+		/// Ensure that the session is unique for each thread.
+		/// </summary>
+		/// <param name="session">The session to store</param>
+		public void Store(SqlMapSession session)
+		{
+			CallContext.SetData(_sessionName, session);
+		}
+
+		/// <summary>
+		/// Remove the local session from the container.
+		/// </summary>
+		public void Dispose()
+		{
+			CallContext.SetData(_sessionName, null);
+		}
+
+		#endregion
+
+		#endregion
+	}
+}

Modified: ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SqlMapper.cs
URL: http://svn.apache.org/viewcvs/ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SqlMapper.cs?rev=232516&r1=232515&r2=232516&view=diff
==============================================================================
--- ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SqlMapper.cs (original)
+++ ibatis/trunk/cs/mapper/IBatisNet.DataMapper/SqlMapper.cs Sat Aug 13 12:00:42 2005
@@ -42,7 +42,6 @@
 using IBatisNet.DataMapper.Configuration.ResultMapping;
 using IBatisNet.DataMapper.Exceptions;
 using IBatisNet.DataMapper.MappedStatements;
-using IBatisNet.DataMapper.SessionContainer;
 using IBatisNet.DataMapper.TypeHandlers;
 
 #endregion
@@ -83,11 +82,13 @@
 
 		private bool _cacheModelsEnabled = false;
 		private bool _useEmbedStatementParams = false;
+		// An identifiant 
+		private string _id = string.Empty;
 
 		/// <summary>
 		/// Container session unique for each thread. 
 		/// </summary>
-		private ISessionContainer _sessionContainer = null;
+		private SessionHolder _sessionHolder = null;
 
 		#endregion
 
@@ -99,7 +100,7 @@
 		/// </summary>
 		public IDalSession LocalSession
 		{
-			get { return _sessionContainer.LocalSession; }
+			get { return _sessionHolder.LocalSession; }
 		}
 
 
@@ -109,7 +110,7 @@
 		/// <returns></returns>
 		public bool IsSessionStarted
 		{
-			get { return (_sessionContainer.LocalSession != null); }
+			get { return (_sessionHolder.LocalSession != null); }
 		}
 
 		/// <summary>
@@ -146,7 +147,8 @@
 		internal SqlMapper(TypeHandlerFactory typeHandlerFactory) 
 		{
 			_typeHandlerFactory = typeHandlerFactory;
-			_sessionContainer = SessionContainerFactory.GetSessionContainer(HashCodeProvider.GetIdentityHashCode(this).ToString());
+			_id = HashCodeProvider.GetIdentityHashCode(this).ToString();
+			_sessionHolder = new SessionHolder(_id);
 		}
 		#endregion
 
@@ -280,12 +282,12 @@
 		/// <returns></returns>
 		public IDalSession OpenConnection() 
 		{
-			if (_sessionContainer.LocalSession != null) 
+			if (_sessionHolder.LocalSession != null) 
 			{
 				throw new DataMapperException("SqlMap could not invoke OpenConnection(). A connection is already started. Call CloseConnection first.");
 			}
 			SqlMapSession session = new SqlMapSession(this);
-			_sessionContainer.Store(session);
+			_sessionHolder.Store(session);
 			session.OpenConnection();
 			return session;
 		}
@@ -295,13 +297,13 @@
 		/// </summary>
 		public void CloseConnection()
 		{
-			if (_sessionContainer.LocalSession == null) 
+			if (_sessionHolder.LocalSession == null) 
 			{
 				throw new DataMapperException("SqlMap could not invoke CloseConnection(). No connection was started. Call OpenConnection() first.");
 			}
 			try
 			{
-				IDalSession session = _sessionContainer.LocalSession;
+				IDalSession session = _sessionHolder.LocalSession;
 				session.CloseConnection();			
 			} 
 			catch(Exception ex)
@@ -310,7 +312,7 @@
 			}
 			finally 
 			{
-				_sessionContainer.Dispose();
+				_sessionHolder.Dispose();
 			}
 		}
 
@@ -320,12 +322,12 @@
 		/// </summary>
 		public IDalSession BeginTransaction() 
 		{
-			if (_sessionContainer.LocalSession != null) 
+			if (_sessionHolder.LocalSession != null) 
 			{
 				throw new DataMapperException("SqlMap could not invoke BeginTransaction(). A Transaction is already started. Call CommitTransaction() or RollbackTransaction first.");
 			}
 			SqlMapSession session = new SqlMapSession(this);
-			_sessionContainer.Store(session);
+			_sessionHolder.Store(session);
 			session.BeginTransaction();
 			return session ;
 		}
@@ -344,7 +346,7 @@
 			}
 			else
 			{
-				session = _sessionContainer.LocalSession;
+				session = _sessionHolder.LocalSession;
 				if (session == null) 
 				{
 					throw new DataMapperException("SqlMap could not invoke BeginTransaction(). A session must be Open. Call OpenConnection() first.");
@@ -363,12 +365,12 @@
 		/// </param>
 		public IDalSession BeginTransaction(IsolationLevel isolationLevel)
 		{
-			if (_sessionContainer.LocalSession != null) 
+			if (_sessionHolder.LocalSession != null) 
 			{
 				throw new DataMapperException("SqlMap could not invoke BeginTransaction(). A Transaction is already started. Call CommitTransaction() or RollbackTransaction first.");
 			}
 			SqlMapSession session = new SqlMapSession(this);
-			_sessionContainer.Store(session);
+			_sessionHolder.Store(session);
 			session.BeginTransaction(isolationLevel);
 			return session;
 		}
@@ -391,7 +393,7 @@
 			}
 			else
 			{
-				session = _sessionContainer.LocalSession;
+				session = _sessionHolder.LocalSession;
 				if (session == null) 
 				{
 					throw new DataMapperException("SqlMap could not invoke BeginTransaction(). A session must be Open. Call OpenConnection() first.");
@@ -409,18 +411,18 @@
 		/// </remarks>
 		public void CommitTransaction()
 		{
-			if (_sessionContainer.LocalSession == null) 
+			if (_sessionHolder.LocalSession == null) 
 			{
 				throw new DataMapperException("SqlMap could not invoke CommitTransaction(). No Transaction was started. Call BeginTransaction() first.");
 			}
 			try
 			{
-				IDalSession session = _sessionContainer.LocalSession;
+				IDalSession session = _sessionHolder.LocalSession;
 				session.CommitTransaction();
 			} 
 			finally 
 			{
-				_sessionContainer.Dispose();
+				_sessionHolder.Dispose();
 			}
 		}
 
@@ -430,20 +432,20 @@
 		/// <param name="closeConnection">Close the connection</param>
 		public void CommitTransaction(bool closeConnection)
 		{
-			if (_sessionContainer.LocalSession == null) 
+			if (_sessionHolder.LocalSession == null) 
 			{
 				throw new DataMapperException("SqlMap could not invoke CommitTransaction(). No Transaction was started. Call BeginTransaction() first.");
 			}
 			try
 			{
-				IDalSession session = _sessionContainer.LocalSession;
+				IDalSession session = _sessionHolder.LocalSession;
 				session.CommitTransaction(closeConnection);
 			} 
 			finally 
 			{
 				if (closeConnection)
 				{
-					_sessionContainer.Dispose();
+					_sessionHolder.Dispose();
 				}
 			}
 		}
@@ -456,18 +458,18 @@
 		/// </remarks>
 		public void RollBackTransaction()
 		{
-			if (_sessionContainer.LocalSession == null) 
+			if (_sessionHolder.LocalSession == null) 
 			{
 				throw new DataMapperException("SqlMap could not invoke RollBackTransaction(). No Transaction was started. Call BeginTransaction() first.");
 			}
 			try
 			{
-				IDalSession session = _sessionContainer.LocalSession;
+				IDalSession session = _sessionHolder.LocalSession;
 				session.RollBackTransaction();			
 			} 
 			finally 
 			{
-				_sessionContainer.Dispose();
+				_sessionHolder.Dispose();
 			}
 		}
 
@@ -477,20 +479,20 @@
 		/// <param name="closeConnection">Close the connection</param>
 		public void RollBackTransaction(bool closeConnection)
 		{
-			if (_sessionContainer.LocalSession == null) 
+			if (_sessionHolder.LocalSession == null) 
 			{
 				throw new DataMapperException("SqlMap could not invoke RollBackTransaction(). No Transaction was started. Call BeginTransaction() first.");
 			}
 			try
 			{
-				IDalSession session = _sessionContainer.LocalSession;
+				IDalSession session = _sessionHolder.LocalSession;
 				session.RollBackTransaction(closeConnection);			
 			} 
 			finally 
 			{
 				if (closeConnection)
 				{
-					_sessionContainer.Dispose();
+					_sessionHolder.Dispose();
 				}
 			}
 		}
@@ -512,7 +514,7 @@
 		public object QueryForObject(string statementName, object parameterObject)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			object result;
  
 			if (session == null) 
@@ -555,7 +557,7 @@
 		public object QueryForObject(string statementName, object parameterObject, object resultObject)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			object result = null;
  
 			if (session == null) 
@@ -647,7 +649,7 @@
 		public IDictionary QueryForMap(string statementName, object parameterObject, string keyProperty, string valueProperty)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			IDictionary map = null;
  
 			if (session == null) 
@@ -696,7 +698,7 @@
 		public IList QueryForList(string statementName, object parameterObject)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			IList list;
  
 			if (session == null) 
@@ -742,7 +744,7 @@
 		public IList QueryForList(string statementName, object parameterObject, int skipResults, int maxResults)	
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			IList list;
  
 			if (session == null) 
@@ -788,7 +790,7 @@
 		public void QueryForList(string statementName, object parameterObject, IList resultObject)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
  
 			if (resultObject == null)
 			{
@@ -856,7 +858,7 @@
 		public IList QueryWithRowDelegate(string statementName, object parameterObject, RowDelegate rowDelegate)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			IList list = null;
  
 			if (session == null) 
@@ -905,7 +907,7 @@
 		public IDictionary QueryForMapWithRowDelegate(string statementName, object parameterObject, string keyProperty, string valueProperty, DictionaryRowDelegate rowDelegate)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			IDictionary map = null;
  
 			if (session == null) 
@@ -960,7 +962,7 @@
 		public object Insert(string statementName, object parameterObject)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			object generatedKey = null;
  
 			if (session == null) 
@@ -1010,7 +1012,7 @@
 		public int Update(string statementName, object parameterObject)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			int rows = 0; // the number of rows affected
 
 			if (session == null) 
@@ -1059,7 +1061,7 @@
 		public int Delete(string statementName, object parameterObject)
 		{
 			bool isSessionLocal = false;
-			IDalSession session = _sessionContainer.LocalSession;
+			IDalSession session = _sessionHolder.LocalSession;
 			int rows = 0; // the number of rows affected
 
 			if (session == null)