在 .netcore 中使用 fluent nhibernate 访问多个数据库
Access multiple databases using fluent nhibernate in .netcore
我是 nHibernate 的新手,正在尝试将它与 .Net 核心一起用于多个 sql 服务器数据库。我浏览了文档并创建了 Isessionfactoty 并在启动时对其进行了配置,但是当我尝试在存储库方法中访问会话对象时,出现错误,因为它只在一个数据库中查找,即 DbConnectionString
我的startup.cs看起来像这样
var sessionFactory = Fluently
.Configure()
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2008
.ShowSql()
.ConnectionString(Configuration.GetConnectionString("DbConnectionString"));
})
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2008
.ShowSql()
.ConnectionString(Configuration.GetConnectionString("AdminDbConnectionString"));
})
.BuildSessionFactory();
services.AddSingleton<NHibernate.ISession>(factory => nHIbernateSession.OpenSession());
这是我的存储库 class,我正在从我的控制器中调用它
public class BusinessRepo
{
ISession _session;
public BusinessRepo(ISession session)
{
_session = session;
}
//This method needs to use DbConnectionString
public PersonGeo GetPersonById(string personId)
{
var value = _session.CreateCriteria<PersonGeo>()
.Add(Restrictions.Eq("Person_ID", personId))
.SetCacheable(true)
.SetCacheMode(CacheMode.Normal)
.List<PersonGeo>();
return value.FirstOrDefault();
}
//This method needs to used AdminDbConnectionString
public List<User> GetAllUsers()
{
//If I debug the _session and look for connection string it is taking "DbConnectionstring (which is configured first in startup)"
var result = _session.CreateSQLQuery("SELECT UserID,UserName,Email,IsActive FROM Users").List<User>();
return result();
}
}
这是我的存储库 class,我正在从我的控制器中调用它
var person = _repo.GetPersonById(personId);
var allUser = _repo.GetAllUsers();
而且我得到找不到对象名称 "tableName" 因为 _session 对象正在查看其他数据库。有人知道如何实施吗?
将您的启动更改为
var dbSessionFatory = Fluently
.Configure()
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2008
.ShowSql()
.ConnectionString(Configuration.GetConnectionString("DbConnectionString"));
})
.BuildSessionFactory();
var adminDbSessionFactory= Fluently
.Configure()
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2008
.ShowSql()
.ConnectionString(Configuration.GetConnectionString("AdminDbConnectionString"));
})
.BuildSessionFactory();
services.AddSingleton<NHibernate.ISession>(factory => dbSessionFatory.OpenSession());
services.AddSingleton<NHibernate.ISession>(factory => adminDbSessionFactory.OpenSession());
然后将 Sessionfactory 的 IEnumerable 注入 repositoy 方法,并为您需要的数据库使用特定的 sessionfactory。
public class BusinessRepo
{
private IEnumerable<ISession> _sessions;
public BusinessRepo(IEnumerable<ISession> sessions)
{
_sessions = sessions;
}
//This method needs to use DbConnectionString
public PersonGeo GetPersonById(string personId)
{
var _session = _sessions.Where(a => a.Connection.Database == "DbName").FirstOrDefault();
var value = _session.CreateCriteria<PersonGeo>()
.Add(Restrictions.Eq("Person_ID", personId))
.SetCacheable(true)
.SetCacheMode(CacheMode.Normal)
.List<PersonGeo>();
return value.FirstOrDefault();
}
//This method needs to used AdminDbConnectionString
public List<User> GetAllUsers()
{
var _session = _sessions.Where(a => a.Connection.Database == "DbName").FirstOrDefault();
//If I debug the _session and look for connection string it is taking "DbConnectionstring (which is configured first in startup)"
var result = _session.CreateSQLQuery("SELECT UserID,UserName,Email,IsActive FROM Users").List<User>();
return result();
}
}
您仍然可以通过创建另一个将数据库名称作为参数和 returns ISession 对象而不是在每个方法中都这样做的方法来重构它
前段时间我遇到了类似的问题,我创建了一个class负责管理多个SessionFactory
在Startup.cs
services.AddSingleton<ISessionSource, SessionSource>();
和class会话源
public class SessionSource : ISessionSource
{
private static readonly object _lockObject = new object();
private static Dictionary<string, ISessionFactory> _sessionFactories = new Dictionary<string, ISessionFactory>();
public SessionSource()
{}
public ISession GetSession(int csName)
{
lock (_lockObject)
{
var session = GetSessionFactory(csName).OpenSession();
return session;
}
}
private FluentConfiguration BaseConfiguration()
{
return Fluently.Configure()
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<MappingCandidate>())
.ExposeConfiguration(cfg =>
{
new SchemaExport(cfg)
.Execute(false, false, false);
});
}
private Configuration AssembleConfiguration(string connectionString)
{
return BaseConfiguration()
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2012
.ConnectionString(connectionString);
})
.BuildConfiguration();
}
private ISessionFactory GetSessionFactory(int csName)
{
var connectionString = Configuration.GetConnectionString(csName);
if (_sessionFactories.ContainsKey(connectionString))
{
return _sessionFactories[connectionString];
}
var sessionFactory = AssembleConfiguration(connectionString).BuildSessionFactory();
_sessionFactories.Add(connectionString, sessionFactory);
return sessionFactory;
}
}
并在例如控制器中
using (var session = _sessionSource.GetSession(connectionStringName))
我是 nHibernate 的新手,正在尝试将它与 .Net 核心一起用于多个 sql 服务器数据库。我浏览了文档并创建了 Isessionfactoty 并在启动时对其进行了配置,但是当我尝试在存储库方法中访问会话对象时,出现错误,因为它只在一个数据库中查找,即 DbConnectionString
我的startup.cs看起来像这样
var sessionFactory = Fluently
.Configure()
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2008
.ShowSql()
.ConnectionString(Configuration.GetConnectionString("DbConnectionString"));
})
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2008
.ShowSql()
.ConnectionString(Configuration.GetConnectionString("AdminDbConnectionString"));
})
.BuildSessionFactory();
services.AddSingleton<NHibernate.ISession>(factory => nHIbernateSession.OpenSession());
这是我的存储库 class,我正在从我的控制器中调用它
public class BusinessRepo
{
ISession _session;
public BusinessRepo(ISession session)
{
_session = session;
}
//This method needs to use DbConnectionString
public PersonGeo GetPersonById(string personId)
{
var value = _session.CreateCriteria<PersonGeo>()
.Add(Restrictions.Eq("Person_ID", personId))
.SetCacheable(true)
.SetCacheMode(CacheMode.Normal)
.List<PersonGeo>();
return value.FirstOrDefault();
}
//This method needs to used AdminDbConnectionString
public List<User> GetAllUsers()
{
//If I debug the _session and look for connection string it is taking "DbConnectionstring (which is configured first in startup)"
var result = _session.CreateSQLQuery("SELECT UserID,UserName,Email,IsActive FROM Users").List<User>();
return result();
}
}
这是我的存储库 class,我正在从我的控制器中调用它
var person = _repo.GetPersonById(personId);
var allUser = _repo.GetAllUsers();
而且我得到找不到对象名称 "tableName" 因为 _session 对象正在查看其他数据库。有人知道如何实施吗?
将您的启动更改为
var dbSessionFatory = Fluently
.Configure()
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2008
.ShowSql()
.ConnectionString(Configuration.GetConnectionString("DbConnectionString"));
})
.BuildSessionFactory();
var adminDbSessionFactory= Fluently
.Configure()
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2008
.ShowSql()
.ConnectionString(Configuration.GetConnectionString("AdminDbConnectionString"));
})
.BuildSessionFactory();
services.AddSingleton<NHibernate.ISession>(factory => dbSessionFatory.OpenSession());
services.AddSingleton<NHibernate.ISession>(factory => adminDbSessionFactory.OpenSession());
然后将 Sessionfactory 的 IEnumerable 注入 repositoy 方法,并为您需要的数据库使用特定的 sessionfactory。
public class BusinessRepo
{
private IEnumerable<ISession> _sessions;
public BusinessRepo(IEnumerable<ISession> sessions)
{
_sessions = sessions;
}
//This method needs to use DbConnectionString
public PersonGeo GetPersonById(string personId)
{
var _session = _sessions.Where(a => a.Connection.Database == "DbName").FirstOrDefault();
var value = _session.CreateCriteria<PersonGeo>()
.Add(Restrictions.Eq("Person_ID", personId))
.SetCacheable(true)
.SetCacheMode(CacheMode.Normal)
.List<PersonGeo>();
return value.FirstOrDefault();
}
//This method needs to used AdminDbConnectionString
public List<User> GetAllUsers()
{
var _session = _sessions.Where(a => a.Connection.Database == "DbName").FirstOrDefault();
//If I debug the _session and look for connection string it is taking "DbConnectionstring (which is configured first in startup)"
var result = _session.CreateSQLQuery("SELECT UserID,UserName,Email,IsActive FROM Users").List<User>();
return result();
}
}
您仍然可以通过创建另一个将数据库名称作为参数和 returns ISession 对象而不是在每个方法中都这样做的方法来重构它
前段时间我遇到了类似的问题,我创建了一个class负责管理多个SessionFactory
在Startup.cs
services.AddSingleton<ISessionSource, SessionSource>();
和class会话源
public class SessionSource : ISessionSource
{
private static readonly object _lockObject = new object();
private static Dictionary<string, ISessionFactory> _sessionFactories = new Dictionary<string, ISessionFactory>();
public SessionSource()
{}
public ISession GetSession(int csName)
{
lock (_lockObject)
{
var session = GetSessionFactory(csName).OpenSession();
return session;
}
}
private FluentConfiguration BaseConfiguration()
{
return Fluently.Configure()
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<MappingCandidate>())
.ExposeConfiguration(cfg =>
{
new SchemaExport(cfg)
.Execute(false, false, false);
});
}
private Configuration AssembleConfiguration(string connectionString)
{
return BaseConfiguration()
.Database(() =>
{
return FluentNHibernate.Cfg.Db.MsSqlConfiguration
.MsSql2012
.ConnectionString(connectionString);
})
.BuildConfiguration();
}
private ISessionFactory GetSessionFactory(int csName)
{
var connectionString = Configuration.GetConnectionString(csName);
if (_sessionFactories.ContainsKey(connectionString))
{
return _sessionFactories[connectionString];
}
var sessionFactory = AssembleConfiguration(connectionString).BuildSessionFactory();
_sessionFactories.Add(connectionString, sessionFactory);
return sessionFactory;
}
}
并在例如控制器中
using (var session = _sessionSource.GetSession(connectionStringName))