如何使用 NHibernate 在单个应用程序中连接到多个数据库?
How to connect to multiple databases in single application with NHibernate?
我们有连接两个Oracle数据库和一个DB2数据库的需求。我们将 NHibernate 5 与 Oracle 的 Oracle 托管数据访问结合使用。
虽然有一些资源可以使用,但大部分都比较老了。
我们处理过单个数据库没有问题,但从未处理过多个数据库。我仍然不知道如何开始。如果有人可以分享一些见解或一些示例代码,我们将不胜感激。
为每个数据库创建和维护单独的 ISessionFactory
实例是可行的方法。所以在你的情况下,你将有三个实例。我已经在我的一个应用程序中实现了这一点,我使用三个不同的 RDBMS 连接到三个数据库。
正如您所说,您已经使用过单一数据库和 NHibernate,我认为不需要任何特定的代码。它是一样的,只是多个会话工厂实例。无论如何,我已经在答案末尾复制了我的代码。
创建 ISession
实例时,请确保您是从要连接的会话工厂实例创建的。您的应用程序的其余部分保持不变。
请注意,它可能会像我遇到的 one 那样在记录时产生问题。但是,那只是一个。其他一切都没有问题。
示例代码:
注意:下面代码中的某些类型不是 NHibernate 类型。那些是它们的包装纸。名字相似;所以理解代码应该没有问题。
public sealed class NHSessionFactory
{
/*
* This must be instance class.
* New instance should be created for each Database Schema.
* Maintain the instance in calling application.
* This is useful if multiple databases are used in one application.
*/
NHSessionFactoryInternal nhSessionFactoryInternal = null;
public void Start(NHSessionFactoryStartParams startParams)
{
Configuration nhConfiguration;
nhConfiguration = new Configuration();
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.Dialect, startParams.Dialect);
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.ConnectionString, startParams.ConnectionString);
if(string.IsNullOrEmpty(startParams.DefaultSchema) == false)
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.DefaultSchema, startParams.DefaultSchema);
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.Isolation, "ReadCommitted");
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.BatchSize, NHSettings.DefaultBatchSize.ToString());
if(string.IsNullOrEmpty(startParams.LogFilePath) == false)
{
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.ShowSql, "true");
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.FormatSql, "true");
}
else
{
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.ShowSql, "false");
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.FormatSql, "false");
}
nhConfiguration.AddMapping(startParams.HbmMappingInstance);
try
{
nhSessionFactoryInternal = new NHSessionFactoryInternal();
nhSessionFactoryInternal.CreateSessionFactory(nhConfiguration);
}
catch(Exception exception)
{
Stop();
throw new NHWrapperException("Failed to create session factory.", exception);
}
}
public void Stop()
{
if(nhSessionFactoryInternal == null)
return;
nhSessionFactoryInternal.CloseSessionFactory();
nhSessionFactoryInternal = null;
}
public INHSession CreateSession(bool readOnly)
{
if(nhSessionFactoryInternal == null)
throw new NHWrapperException("NHWrapper is not started.");
return nhSessionFactoryInternal.CreateNHSession(readOnly);
}
}
及以下是上面代码中使用的 NHSessionFactoryInternal
class 的实现。您可以毫无问题地组合这两个 classes。我在那里还有其他部分;所以我更喜欢把它分开。
internal sealed class NHSessionFactoryInternal
{
ISessionFactory sessionFactory;
internal ISessionFactory SessionFactory { get { return sessionFactory; } }
internal void CreateSessionFactory(Configuration nhConfiguration)
{
if(sessionFactory != null)
throw new NHWrapperException("SessionFactory is already created.");
try
{
sessionFactory = nhConfiguration.BuildSessionFactory();
}
catch(Exception exception)
{
throw new NHWrapperException("Failed to build session factory.", exception);
}
}
internal INHSession CreateNHSession(bool readOnly = false)
{
if(sessionFactory == null)
throw new NHWrapperException("Session factory is not build.");
return new NHSession(sessionFactory.OpenSession(), NHSettings.DefaultFlushMode, readOnly);
}
internal void CloseSessionFactory()
{
if(sessionFactory == null)
return;
if(sessionFactory.IsClosed == false)
sessionFactory.Close();
sessionFactory.Dispose();
sessionFactory = null;
}
}
我们有连接两个Oracle数据库和一个DB2数据库的需求。我们将 NHibernate 5 与 Oracle 的 Oracle 托管数据访问结合使用。 虽然有一些资源可以使用,但大部分都比较老了。
我们处理过单个数据库没有问题,但从未处理过多个数据库。我仍然不知道如何开始。如果有人可以分享一些见解或一些示例代码,我们将不胜感激。
为每个数据库创建和维护单独的 ISessionFactory
实例是可行的方法。所以在你的情况下,你将有三个实例。我已经在我的一个应用程序中实现了这一点,我使用三个不同的 RDBMS 连接到三个数据库。
正如您所说,您已经使用过单一数据库和 NHibernate,我认为不需要任何特定的代码。它是一样的,只是多个会话工厂实例。无论如何,我已经在答案末尾复制了我的代码。
创建 ISession
实例时,请确保您是从要连接的会话工厂实例创建的。您的应用程序的其余部分保持不变。
请注意,它可能会像我遇到的 one 那样在记录时产生问题。但是,那只是一个。其他一切都没有问题。
示例代码:
注意:下面代码中的某些类型不是 NHibernate 类型。那些是它们的包装纸。名字相似;所以理解代码应该没有问题。
public sealed class NHSessionFactory
{
/*
* This must be instance class.
* New instance should be created for each Database Schema.
* Maintain the instance in calling application.
* This is useful if multiple databases are used in one application.
*/
NHSessionFactoryInternal nhSessionFactoryInternal = null;
public void Start(NHSessionFactoryStartParams startParams)
{
Configuration nhConfiguration;
nhConfiguration = new Configuration();
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.Dialect, startParams.Dialect);
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.ConnectionString, startParams.ConnectionString);
if(string.IsNullOrEmpty(startParams.DefaultSchema) == false)
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.DefaultSchema, startParams.DefaultSchema);
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.Isolation, "ReadCommitted");
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.BatchSize, NHSettings.DefaultBatchSize.ToString());
if(string.IsNullOrEmpty(startParams.LogFilePath) == false)
{
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.ShowSql, "true");
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.FormatSql, "true");
}
else
{
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.ShowSql, "false");
nhConfiguration.SetProperty(NHibernate.Cfg.Environment.FormatSql, "false");
}
nhConfiguration.AddMapping(startParams.HbmMappingInstance);
try
{
nhSessionFactoryInternal = new NHSessionFactoryInternal();
nhSessionFactoryInternal.CreateSessionFactory(nhConfiguration);
}
catch(Exception exception)
{
Stop();
throw new NHWrapperException("Failed to create session factory.", exception);
}
}
public void Stop()
{
if(nhSessionFactoryInternal == null)
return;
nhSessionFactoryInternal.CloseSessionFactory();
nhSessionFactoryInternal = null;
}
public INHSession CreateSession(bool readOnly)
{
if(nhSessionFactoryInternal == null)
throw new NHWrapperException("NHWrapper is not started.");
return nhSessionFactoryInternal.CreateNHSession(readOnly);
}
}
及以下是上面代码中使用的 NHSessionFactoryInternal
class 的实现。您可以毫无问题地组合这两个 classes。我在那里还有其他部分;所以我更喜欢把它分开。
internal sealed class NHSessionFactoryInternal
{
ISessionFactory sessionFactory;
internal ISessionFactory SessionFactory { get { return sessionFactory; } }
internal void CreateSessionFactory(Configuration nhConfiguration)
{
if(sessionFactory != null)
throw new NHWrapperException("SessionFactory is already created.");
try
{
sessionFactory = nhConfiguration.BuildSessionFactory();
}
catch(Exception exception)
{
throw new NHWrapperException("Failed to build session factory.", exception);
}
}
internal INHSession CreateNHSession(bool readOnly = false)
{
if(sessionFactory == null)
throw new NHWrapperException("Session factory is not build.");
return new NHSession(sessionFactory.OpenSession(), NHSettings.DefaultFlushMode, readOnly);
}
internal void CloseSessionFactory()
{
if(sessionFactory == null)
return;
if(sessionFactory.IsClosed == false)
sessionFactory.Close();
sessionFactory.Dispose();
sessionFactory = null;
}
}