我们目前正在开发基于NHibernate和ASP.NET MVC以及SQL Server后端的应用程序。由于我是NHibernate的新手,我试着了解最佳实践。
我们的应用程序要求每个用户拥有自己的SQL Server数据库。这些数据库都具有相同的结构。
我们的客户被识别为客户代码,例如1500.
我们已经为nHibernate提供了一个自定义连接提供程序,我们已经在nServiceBus后端服务中使用了它:
public class DynamicConnectionProvider : DriverConnectionProvider
{
public override IDbConnection GetConnection()
{
IDbConnection conn = Driver.CreateConnection();
try
{
var messageExecutionContext = ServiceLocator.Current.GetInstance<ITTTContextProvider>().CurrentContext;
if (messageExecutionContext.CustomerId == 0)
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["dev"]
.ConnectionString;
}
else
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["default"]
.ConnectionString
.FormatWith(messageExecutionContext.CustomerId);
}
conn.Open();
}
catch (Exception)
{
conn.Dispose();
throw;
}
return conn;
}
}
此连接提供程序检查上下文对象中的客户代码并相应地设置连接字符串。
我们计划提供一个HttpContext识别ITTTContextProvider
。为此,我有两个问题:
我们如何从网址检索客户代码并将其放入每个请求的上下文对象中?当我们使用以下路线时?
<main-site-url>/{customercode}/{controller}/{action}/{id}
这种连接多个相同数据库的方法是否有效,或者构建sessionfactory foreach客户数据库是否更好?
答案 0 :(得分:1)
为了获得您需要访问路径数据的customercode
,
HttpContextBase currentContext = new HttpContextWrapper(HttpContext.Current); //ServiceLocator.Current.GetInstance<ITTTContextProvider>().CurrentContext;
RouteData routeData = RouteTable.Routes.GetRouteData(currentContext);
var cusomterCode = routeData.Values["customercode"]
我的第二个建议是不要将此代码放在上面提供的代码段中。抽象它。请参阅Joshua's answer,其中突出了我正在考虑的方法。
对第二个问题无法提供帮助,实际上并不熟悉所提及的两个框架。
答案 1 :(得分:1)
请参阅我最近的博客文章,其中显示了如何使用子域连接到不同的数据库,尽管实现自己的ITenantContext版本很容易从请求URL中获取客户代码。还为每个租户使用单独的会话工厂。
http://www.yellowfeather.co.uk/2011/01/multi-tenancy-on-sharp-architecture/