Andy
Andy

Reputation: 8562

SessionFactory - one factory for multiple databases

We have a situation where we have multiple databases with identical schema, but different data in each. We're creating a single session factory to handle this.

The problem is that we don't know which database we'll connect to until runtime, when we can provide that. But on startup to get the factory build, we need to connect to a database with that schema. We currently do this by creating the schema in an known location and using that, but we'd like to remove that requirement.

I haven't been able to find a way to create the session factory without specifying a connection. We don't expect to be able to use the OpenSession method with no parameters, and that's ok.

Any ideas? Thanks Andy

Upvotes: 5

Views: 2697

Answers (4)

Taber Loveless
Taber Loveless

Reputation: 33

Came across this and thought Id add my solution for future readers which is basically what Mauricio Scheffer has suggested which encapsulates the 'switching' of CS and provides single point of management (I like this better than having to pass into each session call, less to 'miss' and go wrong).

I obtain the connecitonstring during authentication of the client and set on the context then, using the following IConnectinProvider implementation, set that value for the CS whenever a session is opened:

/// <summary>
/// Provides ability to switch connection strings of an NHibernate Session Factory (use same factory for multiple, dynamically specified, database connections)
/// </summary>
public class DynamicDriverConnectionProvider : DriverConnectionProvider, IConnectionProvider
{
    protected override string ConnectionString
    {
        get
        {
            var cxnObj = IsWebContext ?
                HttpContext.Current.Items["RequestConnectionString"]: 
                System.Runtime.Remoting.Messaging.CallContext.GetData("RequestConnectionString");

            if (cxnObj != null)
                return cxnObj.ToString();
            //catch on app startup when there is not request connection string yet set
            return base.ConnectionString;
        }
    }

    private static bool IsWebContext
    {
        get { return (HttpContext.Current != null); }
    }
}

Then wire it in during NHConfig:

var configuration = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2005
                            .Provider<DynamicDriverConnectionProvider>() //Like so

Upvotes: 0

Rob Angelier
Rob Angelier

Reputation: 2333

You could also use the great NuGet package from brady gaster for this. I made my own implementation from his NHQS package and it works very well.

You can find it here:

http://www.bradygaster.com/Tags/nhqs

good luck!

Upvotes: 0

Andy
Andy

Reputation: 8562

The solution we came up with was to create a class which manages this for us. The class can use some information in the method call to do some routing logic to figure out where the database is, and then call OpenSession passing the connection string.

Upvotes: 0

Mauricio Scheffer
Mauricio Scheffer

Reputation: 99720

Either implement your own IConnectionProvider or pass your own connection to ISessionFactory.OpenSession(IDbConnection) (but read the method's comments about connection tracking)

Upvotes: 2

Related Questions