每个租户的数据库使用 Fluent NHibernate &结构图
我目前正在使用 StructureMap 将 NHibernateRegistry
实例注入到我的 DAL 中,该实例为单个连接字符串配置 NHibernate,并为我的单用户应用程序引导 Singleton FluentConfiguration
。
我应该如何修改 Fluent NHibernate 配置以根据路由 URL 中的 {tenant}
路由参数使用不同的数据库?
路由示例:
{tenant}/{controller}/{action}/{id}
...其中对 branch1/Home/Index
和 branch2/Home/Index
的请求使用相同的应用程序代码,但使用不同的数据库来检索显示的数据。
我过去通过注入每个请求的 TenantContext 对象解决了 StructureMap 和 LINQ 的这个问题,该对象从它接受为构造函数参数并指定的 HttpContext 中检索路由参数不同的 LINQ 数据上下文。
然而,我怀疑 NHibernate 能够比我想象的更好地处理这个问题。
部分 NHibernateRegistry
类
public class NHibernateRegistry : Registry
{
// ... private vars here
public NHibernateRegistry()
{
var cfg = Fluently.Configure()
.Database(MsSqlConfiguration
.MsSql2008.ConnectionString(c =>
c.FromConnectionStringWithKey("TenantConnectionStringKey")))
// where to inject this key?
.ExposeConfiguration(BuildSchema)
.Mappings(x =>
x.FluentMappings.AddFromAssembly(typeof(UserMap).Assembly)
For<FluentConfiguration>().Singleton().Use(cfg);
var sessionFactory = cfg.BuildSessionFactory();
For<ISessionFactory>().Singleton()
.Use(sessionFactory);
For<ISession>().HybridHttpOrThreadLocalScoped()
.Use(x => x.GetInstance<ISessionFactory>().OpenSession());
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped()
.Use<UnitOfWork>();
For<IDatabaseBuilder>().Use<DatabaseBuilder>();
}
}
StructureMap 配置:
public static class Bootstrapper
{
public static void ConfigureStructureMap()
{
ObjectFactory.Initialize(Init);
}
private static void Init(IInitializationExpression x)
{
x.AddRegistry(new NHibernateRegistry()); // from Data project
}
}
我是 NHibernate 的新手,所以我不确定我的会话和配置的范围。 NHibernate 有内置的方法来处理这个问题吗?
I'm currently using StructureMap to inject an NHibernateRegistry
instance into my DAL, which configures NHibernate for a single connection string and bootstraps a Singleton FluentConfiguration
for my single-user app.
How should I modify my Fluent NHibernate configuration to use a different database based on a {tenant}
routing parameter in my routing URL?
Routing example:
{tenant}/{controller}/{action}/{id}
...where requests for branch1/Home/Index
and branch2/Home/Index
use the same application code, but different databases to retrieve the data displayed.
I solved this problem in the past for StructureMap and LINQ by injecting a per-request TenantContext
object, which retrieved the routing parameter from the HttpContext
it accepted as a constructor parameter and specified a different LINQ data context.
However, I suspect NHibernate has a better of handling this than I could cook up.
Partial NHibernateRegistry
class
public class NHibernateRegistry : Registry
{
// ... private vars here
public NHibernateRegistry()
{
var cfg = Fluently.Configure()
.Database(MsSqlConfiguration
.MsSql2008.ConnectionString(c =>
c.FromConnectionStringWithKey("TenantConnectionStringKey")))
// where to inject this key?
.ExposeConfiguration(BuildSchema)
.Mappings(x =>
x.FluentMappings.AddFromAssembly(typeof(UserMap).Assembly)
For<FluentConfiguration>().Singleton().Use(cfg);
var sessionFactory = cfg.BuildSessionFactory();
For<ISessionFactory>().Singleton()
.Use(sessionFactory);
For<ISession>().HybridHttpOrThreadLocalScoped()
.Use(x => x.GetInstance<ISessionFactory>().OpenSession());
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped()
.Use<UnitOfWork>();
For<IDatabaseBuilder>().Use<DatabaseBuilder>();
}
}
StructureMap configuration:
public static class Bootstrapper
{
public static void ConfigureStructureMap()
{
ObjectFactory.Initialize(Init);
}
private static void Init(IInitializationExpression x)
{
x.AddRegistry(new NHibernateRegistry()); // from Data project
}
}
I'm new to NHibernate, so I am unsure of scoping my sessions and configurations. Does NHibernate have a built-in way to handle this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这在模块中对我有用
This worked for me in an a module
问题是您确实希望您的 ISessionFactory 对象成为单例。这意味着在创建
ISessionFactory
时最好不要指定连接字符串。您是否尝试过在不指定连接字符串的情况下创建ISessionFactory
,然后将手动创建的连接传递给ISessionFactory.OpenSession
?例如:
然后告诉StructureMap调用这个方法。
缺点是您现在无法在创建 ISessionFactory 时构建数据库架构,但也许在 Web 应用程序中创建数据库架构不是一个好主意吗?
The problem is that you really want your
ISessionFactory
object to be a singleton. This means its best not to specify the connection string when creating theISessionFactory
. Have your tried creating theISessionFactory
without specifying a connection string and then passing a manually created connection toISessionFactory.OpenSession
?For example:
And then tell StructureMap to call this method.
The downside is that you can't now from build the database schema when creating the
ISessionFactory
, but maybe creating database schemas in web applications isn't that great an idea anyway?