【发布时间】:2008-09-18 11:49:34
【问题描述】:
谁能最终解释一下在 NHibernate 驱动的域模型中实现对多租户功能的透明和流畅支持的最佳策略是什么?
我正在寻找方法,如何使域逻辑与多租户的东西尽可能隔离,例如通过 TenantID 过滤等
【问题讨论】:
标签: .net nhibernate domain-driven-design saas
谁能最终解释一下在 NHibernate 驱动的域模型中实现对多租户功能的透明和流畅支持的最佳策略是什么?
我正在寻找方法,如何使域逻辑与多租户的东西尽可能隔离,例如通过 TenantID 过滤等
【问题讨论】:
标签: .net nhibernate domain-driven-design saas
最简单的方法是为每个客户端使用不同的数据库。
以这种方式实现多租户允许您有效地编写单租户应用程序,而只需担心创建/检索会话时的多租户。
我还没有深入研究细节(我需要在几个月内做类似的事情),但我认为管理会话连接到哪个数据库的最简单方法是通过自定义 ISessionFactory 实现,它可以确定要使用的连接(基于外部方面,例如请求 url 的主机部分)。
我在网上看到至少一篇讨论这个问题的帖子,但我目前找不到链接。
如果您使用的是 Castle Windsor,请查看 NHibernate 集成工具。这支持多个(命名的)会话工厂的概念,这将允许您为每个客户端拥有一个会话工厂。集成工具提供了一个 ISessionManager 接口,允许您在命名会话工厂上打开会话(以及为 Web 应用程序提供每个请求的会话语义)。任何需要访问会话的东西都可以简单地采用 ISession 构造函数参数,并且您可以创建一个将 ISessionManager 作为构造函数参数的工厂。然后,您的工厂可以通过检查请求以确定应该使用哪个命名会话工厂来在适当的命名会话工厂上打开一个会话。
【讨论】:
我最近也在为我的下一个项目深入研究它。 您可以实现自定义 IConnectionProvider 并使用“connection.provider”将其注册到配置中。
我建议你从 DriverConnectionProvider 派生并覆盖 ConnectionString 而不是实现一个完全自定义的。
可能是这样的:
public class ContextualConnectionProvider : DriverConnectionProvider
{
protected override string ConnectionString
{
get
{
return GetCurrentTenantDatabaseConnectionStringInternally();
}
}
public override void Configure(IDictionary<string, string> settings)
{
ConfigureDriver(settings);
}
}
希望这会有所帮助。
【讨论】:
我在博客上写了一个多租户here 的方法,该方法并不适用于所有情况,但是,它确实可以让您在很大程度上忘记多租户问题,而无需使用第 3 方产品。
【讨论】:
Ayende 有一些关于构建多租户应用程序的好博文。如何使用 NHibernate 取决于您要使用的多租户类型。
【讨论】:
使用共享架构方法需要您拦截所有查询并用附加信息修饰所有查询以限制结果。
NHibernate 提供拦截器来执行此操作,事件侦听器也可从 NHibernate 2.0 Aplpha 1 获得。
请参阅 http://elegantcode.com/2008/05/15/implementing-nhibernate-interceptors/ 和 http://www.codinginstinct.com/2008/04/nhibernate-20-events-and-listeners.html 了解有关这些内容的讨论。
还可以查看 Ayende 的 Rhino 安全组件,因为他在这方面做了很多工作,以根据安全描述符修改带有附加限制的查询。您可以在https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/security浏览源代码
【讨论】: