Managing multiple databases with NHibernate and Autofac

I thought I'd get this question out there while I noodled on a solution on my own.

After having built out the bulk of an application, I have a last minute requirement to support reading/writing to an additional database (2 total, no known others). I built the application using NHibernate, with Autofac supplying the DI/IoC components. FWIW, this resides in an ASP.NET MVC 2 app.

I have a generic repository class that takes an NHibernate session. Theoretically, I can continue to use this generic repository (IRepository) for the second database so long as the session that gets passed to it is spawned from an appropriate SessionFactory, right?

Well, when the app starts, Autofac does it's thing. With regards to the Session and SessionFactory, I have a module that states:

builder.Register(c => c.Resolve().OpenSession())
    .InstancePerMatchingLifetimeScope(WebLifetime.Request)
    .OnActivated(e =>
    {
        e.Context.Resolve().CurrentTransaction = ((ISession)e.Instance).BeginTransaction();
    });

 builder.Register(c => ConfigureNHibernate())
    .SingleInstance();

where ConfigureNHibernate(), which returns the base SessionFactory, looks like:

private ISessionFactory ConfigureNHibernate()
{
    Configuration cfg = new Configuration().Configure();
    cfg.AddAssembly(typeof(Entity).Assembly);
    return cfg.Configure().BuildSessionFactory();
}

Currently, this is limited to just the one database. In any other NHib scenario, I'd likely shove instances of the separate SessionFactories into a hash, and retrieve them as needed. I don't want to have to re-architect the whole thing as we're fairly close to a major release. So, I'm guessing I need to modify at least the methods above so that I can independently configure two SessionFactories. My gray area is how I'll go about specifying the correct Factory be used with a specific repository (or at least for entities specific to that second database).

Anyone have experience with this scenario while using an IoC container and NHibernate in this manner?

EDIT I've stubbed out a GetSessionFactory method that takes a configuration file path, checks for the existance of a matching SessionFactory in the HttpRuntime.Cache, creates a new instance if one doesn't already exist, and returns that SessionFactory. Now I still need to hammer out how to tell Autofac how and when to specify an appropriate config path. The new method looks like (borrowed heavily from Billy's 2006 post here):

private ISessionFactory GetSessionFactory(string sessionFactoryConfigPath)
    {
        Configuration cfg = null;
        var sessionFactory = (ISessionFactory)HttpRuntime.Cache.Get(sessionFactoryConfigPath);

        if (sessionFactory == null)
        {
            if (!File.Exists(sessionFactoryConfigPath))
                throw new FileNotFoundException("The nhibernate configuration file at '" + sessionFactoryConfigPath + "' could not be found.");

            cfg = new Configuration().Configure(sessionFactoryConfigPath);
            sessionFactory = cfg.BuildSessionFactory();

            if (sessionFactory == null)
            {
                throw new Exception("cfg.BuildSessionFactory() returned null.");
            }

            HttpRuntime.Cache.Add(sessionFactoryConfigPath, sessionFactory, null, DateTime.Now.AddDays(7), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null);
        }

        return sessionFactory;
    }

8
задан nkirkes 14 December 2010 в 21:41
поделиться