问题
So I have multi db instances and One web application. depending on the url name, I know what db instance I need to talk to. I want to change the old ugly DAL to work with nhibernate and I want to use DI to do that. so, let say I have this class:
class CompanyDal(ISession session) //nhibernate session
{
Save(ICompany company)
{
session.Save(company)
}
}
so I am injecting the hibernate session when creating the DAL object. but my IOC needs to know which session to inject, meaning which connection string. If I have only one singleton factory I will get the wrong session for different urls (different db)
I hope I explained it so you all can understand. thank you
回答1:
Assuming all the databases have the same schema, you can dynamically switch the connection using a custom DriverConnectionProvider. In the code below I am loading the connection strings from web.config into a dictionary, then retrieving them using a "tenant" route value from the URL.
public class TenantConnectionProvider : DriverConnectionProvider
{
private IDictionary<string, string> _tenantConnectionStrings;
public override void Configure(IDictionary<string, string> settings)
{
// Load connection strings from config file
_tenantConnectionStrings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (ConnectionStringSettings connectionStringSetting in ConfigurationManager.ConnectionStrings)
{
_tenantConnectionStrings.Add(connectionStringSetting.Name, connectionStringSetting.ConnectionString);
}
base.Configure(settings);
}
public override IDbConnection GetConnection()
{
var connectionString = GetConnectionString(); //not shown, mine is for Web API
var connection = new SqlConnection(connectionString);
connection.Open();
return connection;
}
}
I then configure this using Fluent NHibernate:
// connection string has to be set even though custom provider is used
var config = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString("custom").Provider<TenantConnectionProvider>)
.Mappings(m =>
{
m.FluentMappings.AddFromAssemblyOf<MyClass>();
});
回答2:
You will have to have 2 SessionFactories (1 per db) and register a named session for each one.
I've experience only with Autofac (other IoC should work the same)
.Register<ISession>(factory1.OpenSession()).Named("f1");
.Register<ISession>(factory2.OpenSession()).Named("f2");
An enum instead of string can be used.
Given that the session is dependent on the url in some way (and IoC integration is used), the only easy way that I see is with an activation handler:
.Register<IRepository>().OnActivating(e => {
var db = HttpContext.Current.Request.Url....//some code to find the db
var dep = e.Context.Resolve<ISession>("f1");
e.Instance.SetTheDependency(dep);})
or property injection
来源:https://stackoverflow.com/questions/21887553/using-nhibernate-with-multi-db-instances-with-di