SPRNET-1301
Added support for runtime resolution of multiple concurrent NHibernate Session Factories
This commit is contained in:
@@ -1,19 +1,19 @@
|
||||
#region License
|
||||
|
||||
/*
|
||||
* Copyright <20> 2002-2005 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 <20> 2002-2005 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
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Data;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NHibernate;
|
||||
using NHibernate.Cfg;
|
||||
using NHibernate.Connection;
|
||||
|
||||
using Spring.Data.NHibernate;
|
||||
|
||||
namespace Spring.Data.NHibernate
|
||||
{
|
||||
///<summary>
|
||||
/// Delegates to an implementation of ISessionFactory that can select among multiple instances based on
|
||||
/// thread local storage.
|
||||
///</summary>
|
||||
public class DelegatingLocalSessionFactoryObject : LocalSessionFactoryObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Subclasses can override this method to perform custom initialization
|
||||
/// of the SessionFactory instance, creating it via the given Configuration
|
||||
/// object that got prepared by this LocalSessionFactoryObject.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <p>The default implementation invokes Configuration's BuildSessionFactory.
|
||||
/// A custom implementation could prepare the instance in a specific way,
|
||||
/// or use a custom ISessionFactory subclass.
|
||||
/// </p>
|
||||
/// </remarks>
|
||||
/// <returns>The ISessionFactory instance.</returns>
|
||||
protected override ISessionFactory NewSessionFactory(Configuration config)
|
||||
{
|
||||
return new SimpleDelegatingSessionFactory(config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PostProcessConfiguration
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
protected override void PostProcessConfiguration(Configuration config)
|
||||
{
|
||||
// called before NewSessionFactory
|
||||
if (!config.Properties.ContainsKey(Environment.ConnectionString))
|
||||
{
|
||||
throw new System.ArgumentException("Must specify connection string");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
using System.Data;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using NHibernate;
|
||||
using NHibernate.Cfg;
|
||||
using NHibernate.Connection;
|
||||
using NHibernate.Dialect;
|
||||
using NHibernate.Engine;
|
||||
using NHibernate.Metadata;
|
||||
using NHibernate.Stat;
|
||||
|
||||
namespace Spring.Data.NHibernate
|
||||
{
|
||||
#pragma warning disable 1591
|
||||
/// <summary>
|
||||
/// DelegatingSessionFactory class
|
||||
/// </summary>
|
||||
public abstract class DelegatingSessionFactory : ISessionFactory
|
||||
{
|
||||
public ICollection<string> DefinedFilterNames
|
||||
{
|
||||
get { return TargetSessionFactory.DefinedFilterNames; }
|
||||
}
|
||||
|
||||
public bool IsClosed
|
||||
{
|
||||
get { return TargetSessionFactory.IsClosed; }
|
||||
}
|
||||
|
||||
public IStatistics Statistics
|
||||
{
|
||||
get { return TargetSessionFactory.Statistics; }
|
||||
}
|
||||
|
||||
public abstract ISessionFactory TargetSessionFactory
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
TargetSessionFactory.Close();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
TargetSessionFactory.Dispose();
|
||||
}
|
||||
|
||||
public void Evict(System.Type persistentClass, object id)
|
||||
{
|
||||
TargetSessionFactory.Evict(persistentClass, id);
|
||||
}
|
||||
|
||||
public void Evict(System.Type persistentClass)
|
||||
{
|
||||
TargetSessionFactory.Evict(persistentClass);
|
||||
}
|
||||
|
||||
public void EvictCollection(string roleName, object id)
|
||||
{
|
||||
TargetSessionFactory.EvictCollection(roleName, id);
|
||||
}
|
||||
|
||||
public void EvictCollection(string roleName)
|
||||
{
|
||||
TargetSessionFactory.EvictCollection(roleName);
|
||||
}
|
||||
|
||||
public void EvictEntity(string entityName)
|
||||
{
|
||||
TargetSessionFactory.EvictEntity(entityName);
|
||||
}
|
||||
|
||||
public void EvictEntity(string entityName, object id)
|
||||
{
|
||||
TargetSessionFactory.EvictEntity(entityName, id);
|
||||
}
|
||||
|
||||
public void EvictQueries(string cacheRegion)
|
||||
{
|
||||
TargetSessionFactory.EvictQueries(cacheRegion);
|
||||
}
|
||||
|
||||
public void EvictQueries()
|
||||
{
|
||||
TargetSessionFactory.EvictQueries();
|
||||
}
|
||||
|
||||
public IDictionary<string, IClassMetadata> GetAllClassMetadata()
|
||||
{
|
||||
return TargetSessionFactory.GetAllClassMetadata();
|
||||
}
|
||||
|
||||
public IDictionary<string, ICollectionMetadata> GetAllCollectionMetadata()
|
||||
{
|
||||
return TargetSessionFactory.GetAllCollectionMetadata();
|
||||
}
|
||||
|
||||
public IClassMetadata GetClassMetadata(System.Type persistentType)
|
||||
{
|
||||
return TargetSessionFactory.GetClassMetadata(persistentType);
|
||||
}
|
||||
|
||||
public IClassMetadata GetClassMetadata(string entityName)
|
||||
{
|
||||
return TargetSessionFactory.GetClassMetadata(entityName);
|
||||
}
|
||||
|
||||
public ICollectionMetadata GetCollectionMetadata(string roleName)
|
||||
{
|
||||
return TargetSessionFactory.GetCollectionMetadata(roleName);
|
||||
}
|
||||
|
||||
public ISession GetCurrentSession()
|
||||
{
|
||||
return TargetSessionFactory.GetCurrentSession();
|
||||
}
|
||||
|
||||
public FilterDefinition GetFilterDefinition(string filterName)
|
||||
{
|
||||
return TargetSessionFactory.GetFilterDefinition(filterName);
|
||||
}
|
||||
|
||||
public ISession OpenSession(IInterceptor interceptor)
|
||||
{
|
||||
return TargetSessionFactory.OpenSession(interceptor);
|
||||
}
|
||||
|
||||
public ISession OpenSession()
|
||||
{
|
||||
return TargetSessionFactory.OpenSession();
|
||||
}
|
||||
|
||||
public ISession OpenSession(IDbConnection conn, IInterceptor interceptor)
|
||||
{
|
||||
return TargetSessionFactory.OpenSession(conn, interceptor);
|
||||
}
|
||||
|
||||
public ISession OpenSession(IDbConnection conn)
|
||||
{
|
||||
return TargetSessionFactory.OpenSession(conn);
|
||||
}
|
||||
|
||||
public IStatelessSession OpenStatelessSession()
|
||||
{
|
||||
return TargetSessionFactory.OpenStatelessSession();
|
||||
}
|
||||
|
||||
public IStatelessSession OpenStatelessSession(IDbConnection connection)
|
||||
{
|
||||
return TargetSessionFactory.OpenStatelessSession(connection);
|
||||
}
|
||||
|
||||
IDictionary<string, IClassMetadata> ISessionFactory.GetAllClassMetadata()
|
||||
{
|
||||
return TargetSessionFactory.GetAllClassMetadata();
|
||||
}
|
||||
|
||||
IDictionary<string, ICollectionMetadata> ISessionFactory.GetAllCollectionMetadata()
|
||||
{
|
||||
return TargetSessionFactory.GetAllCollectionMetadata();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System.Collections;
|
||||
|
||||
using NHibernate;
|
||||
using NHibernate.Cfg;
|
||||
using NhCfg = NHibernate.Cfg;
|
||||
|
||||
using Spring.Collections;
|
||||
using Spring.Threading;
|
||||
using Spring.Data.Common;
|
||||
using Spring.Context.Support;
|
||||
using NHibernate.Engine;
|
||||
using System;
|
||||
|
||||
namespace Spring.Data.NHibernate
|
||||
{
|
||||
/// <summary>
|
||||
/// SimpleDelegatingSessionFactory class
|
||||
/// </summary>
|
||||
public class SimpleDelegatingSessionFactory : DelegatingSessionFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Connection string config element name
|
||||
/// </summary>
|
||||
public const string CONNECTION_STRING = "SimpleDelegatingSessionFactory.ConnectionString";
|
||||
|
||||
private Configuration _configuration;
|
||||
|
||||
private string _defaultConnectionString;
|
||||
|
||||
private object _monitor = new object();
|
||||
|
||||
private IDictionary _targetSessionFactories = new SynchronizedHashtable();
|
||||
|
||||
/// <summary>
|
||||
/// public Constructor
|
||||
/// </summary>
|
||||
/// <param name="defaultConfiguration"></param>
|
||||
public SimpleDelegatingSessionFactory(Configuration defaultConfiguration)
|
||||
{
|
||||
if (defaultConfiguration == null)
|
||||
{
|
||||
throw new ArgumentException("Configuration cannot be null", "defaultConfiguration");
|
||||
}
|
||||
|
||||
_configuration = defaultConfiguration;
|
||||
if (!_configuration.Properties.ContainsKey(NhCfg.Environment.ConnectionString))
|
||||
{
|
||||
throw new ArgumentException("Must specify connection string");
|
||||
}
|
||||
|
||||
_defaultConnectionString = _configuration.Properties[NhCfg.Environment.ConnectionString] as string;
|
||||
if (_defaultConnectionString == null)
|
||||
{
|
||||
throw new ArgumentException("Connection string property must be of type string, not " +
|
||||
_configuration.Properties[NhCfg.Environment.ConnectionString].GetType().FullName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TargetSessionFactory
|
||||
/// </summary>
|
||||
public override ISessionFactory TargetSessionFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
string connectionString = LogicalThreadContext.GetData(CONNECTION_STRING) as string;
|
||||
|
||||
System.Diagnostics.Trace.WriteLine(String.Format("{0} = {1}", System.Threading.Thread.CurrentThread.GetHashCode(), connectionString));
|
||||
|
||||
if (connectionString == null)
|
||||
{
|
||||
connectionString = _defaultConnectionString;
|
||||
}
|
||||
|
||||
lock (_monitor)
|
||||
{
|
||||
if (!_targetSessionFactories.Contains(connectionString))
|
||||
{
|
||||
System.Diagnostics.Trace.WriteLine(System.Threading.Thread.CurrentThread.GetHashCode().ToString() + " = (created) ");
|
||||
|
||||
_configuration.Properties[NhCfg.Environment.ConnectionString] = connectionString;
|
||||
ISessionFactory sessionFactory = _configuration.BuildSessionFactory();
|
||||
|
||||
LocalSessionFactoryObject.DbProviderWrapper dbProviderWrapper = ((ISessionFactoryImplementor)sessionFactory).ConnectionProvider as LocalSessionFactoryObject.DbProviderWrapper;
|
||||
if (dbProviderWrapper != null)
|
||||
{
|
||||
dbProviderWrapper.DbProvider = (IDbProvider)ContextRegistry.GetContext().GetObject("DbProvider");
|
||||
}
|
||||
|
||||
_targetSessionFactories[connectionString] = sessionFactory;
|
||||
}
|
||||
else
|
||||
System.Diagnostics.Trace.WriteLine(System.Threading.Thread.CurrentThread.GetHashCode().ToString() + " = (cached) ");
|
||||
|
||||
ISessionFactory factory = _targetSessionFactories[connectionString] as ISessionFactory;
|
||||
|
||||
System.Diagnostics.Trace.WriteLine(String.Format("{0} = {1}", System.Threading.Thread.CurrentThread.GetHashCode(), ((ISessionFactoryImplementor)factory).ConnectionProvider.GetConnection().ConnectionString));
|
||||
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -167,6 +167,9 @@
|
||||
<Compile Include="Data\NHibernate\Bytecode\ReflectionOptimizer.cs" />
|
||||
<Compile Include="Data\NHibernate\Bytecode\BytecodeProvider.cs" />
|
||||
<Compile Include="Data\NHibernate\Bytecode\ObjectsFactory.cs" />
|
||||
<Compile Include="Data\NHibernate\DelegatingLocalSessionFactoryObject.cs" />
|
||||
<Compile Include="Data\NHibernate\DelegatingSessionFactory.cs" />
|
||||
<Compile Include="Data\NHibernate\SimpleDelegatingSessionFactory.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Spring.Aop\Spring.Aop.2010.csproj">
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
<include name="../Spring.Data.NHibernate12/Data/**/*.cs" />
|
||||
<include name="../Spring.Data.NHibernate12/Support/**/*.cs" />
|
||||
<include name="../Spring.Data.NHibernate20/Data/**/*.cs" />
|
||||
<include name="../Spring.Data.NHibernate21/Data/**/*.cs" />
|
||||
<exclude name="../Spring.Data.NHibernate/Data/**/HibernateAccessor.cs" />
|
||||
<exclude name="../Spring.Data.NHibernate/Data/**/SpringSessionSynchronization.cs" />
|
||||
<exclude name="../Spring.Data.NHibernate/Data/**/LocalSessionFactoryObject.cs" />
|
||||
|
||||
@@ -107,6 +107,15 @@
|
||||
<Compile Include="..\Spring.Data.NHibernate21\Data\NHibernate\Bytecode\ReflectionOptimizer.cs">
|
||||
<Link>Data\NHibernate\Bytecode\ReflectionOptimizer.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate21\Data\NHibernate\DelegatingLocalSessionFactoryObject.cs">
|
||||
<Link>Data\NHibernate\DelegatingLocalSessionFactoryObject.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate21\Data\NHibernate\DelegatingSessionFactory.cs">
|
||||
<Link>Data\NHibernate\DelegatingSessionFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate21\Data\NHibernate\SimpleDelegatingSessionFactory.cs">
|
||||
<Link>Data\NHibernate\SimpleDelegatingSessionFactory.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Spring.Data.NHibernate\Data\NHibernate\HibernateAdoException.cs">
|
||||
<Link>Data\NHibernate\HibernateAdoException.cs</Link>
|
||||
</Compile>
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
<include name="../Spring.Data.NHibernate12/Support/**/*.cs" />
|
||||
<include name="../Spring.Data.NHibernate20/Data/**/*.cs" />
|
||||
<include name="../Spring.Data.NHibernate21/Data/**/*.cs" />
|
||||
<include name="../Spring.Data.NHibernate21/Data/**/*.cs" />
|
||||
<exclude name="../Spring.Data.NHibernate/Data/**/HibernateAccessor.cs" />
|
||||
<exclude name="../Spring.Data.NHibernate/Data/**/SpringSessionSynchronization.cs" />
|
||||
<exclude name="../Spring.Data.NHibernate/Data/**/LocalSessionFactoryObject.cs" />
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
using NhCfg = NHibernate.Cfg;
|
||||
using NHibernate;
|
||||
using System.Collections;
|
||||
using Spring.Data.Common;
|
||||
using NHibernate.Dialect;
|
||||
using Spring.Context.Support;
|
||||
using NHibernate.Connection;
|
||||
using NHibernate.Driver;
|
||||
using Spring.Data.NHibernate.Bytecode;
|
||||
|
||||
namespace Spring.Data.NHibernate
|
||||
{
|
||||
|
||||
[TestFixture]
|
||||
public class DelegatingLocalSessionFactoryObjectTests
|
||||
{
|
||||
[Test]
|
||||
public void CanSetConfigurationAndProperties()
|
||||
{
|
||||
IDbProvider dbProvider = DbProviderFactory.GetDbProvider("System.Data.SqlClient");
|
||||
dbProvider.ConnectionString = "Data Source=(local);Database=Spring;Trusted_Connection=false";
|
||||
DelegatingLocalSessionFactoryObject lsfo = new DelegatingLocalSessionFactoryObject();
|
||||
lsfo.DbProvider = dbProvider;
|
||||
lsfo.ApplicationContext = new StaticApplicationContext();
|
||||
|
||||
IDictionary properties = new Hashtable();
|
||||
properties.Add(NhCfg.Environment.Dialect, typeof(MsSql2000Dialect).AssemblyQualifiedName);
|
||||
properties.Add(NhCfg.Environment.ConnectionDriver, typeof(SqlClientDriver).AssemblyQualifiedName);
|
||||
properties.Add(NhCfg.Environment.ConnectionProvider, typeof(DriverConnectionProvider).AssemblyQualifiedName);
|
||||
|
||||
properties.Add(NhCfg.Environment.Hbm2ddlKeyWords, "none");
|
||||
|
||||
lsfo.HibernateProperties = properties;
|
||||
lsfo.AfterPropertiesSet();
|
||||
|
||||
Assert.IsNotNull(lsfo.Configuration);
|
||||
Assert.AreEqual(lsfo.Configuration.Properties[NhCfg.Environment.ConnectionProvider], typeof(DriverConnectionProvider).AssemblyQualifiedName);
|
||||
Assert.AreEqual(lsfo.Configuration.Properties[NhCfg.Environment.ConnectionDriver], typeof(SqlClientDriver).AssemblyQualifiedName);
|
||||
Assert.AreEqual(lsfo.Configuration.Properties[NhCfg.Environment.Dialect], typeof(MsSql2000Dialect).AssemblyQualifiedName);
|
||||
|
||||
Assert.AreEqual(lsfo.Configuration.Properties[NhCfg.Environment.ProxyFactoryFactoryClass], typeof(ProxyFactoryFactory).AssemblyQualifiedName);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -98,6 +98,7 @@
|
||||
<Link>Data\NHibernate\TestObject.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AssemblyInfo.cs" />
|
||||
<Compile Include="Data\NHibernate\DelegatingLocalSessionFactoryObjectTests.cs" />
|
||||
<Compile Include="HibernateCompilerOptionsTests.cs" />
|
||||
<Compile Include="HibernateExceptionTests.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user