user3329192
user3329192

Reputation: 1

using nHibernate with multi DB instances with DI

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

Upvotes: 0

Views: 404

Answers (2)

Boklucius
Boklucius

Reputation: 1926

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

Upvotes: 0

Jamie Ide
Jamie Ide

Reputation: 49261

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>();
    });

Upvotes: 2

Related Questions