Extending NHibernate’s DriverConnectionProvider
Posted by Davy Brion on September 18th, 2008
Ahh, i’m finally able to use NHibernate again at work, so expect more NHibernate related posts in the future
Today i needed a way to add some functionality when NHibernate opens a database connection, and again when NHibernate closes the connection. When the connection is opened, i need to setup some context on the connection for auditing purposes and it needs to be cleared again when the connection is closed. So i started searching on how to plug this into NHibernate. As usual, this was trivially easy to do.
All you need to do is create a type that implements the IConnectionProvider interface. In my case, i only needed to add a bit of behavior so i could just derive from NHibernate’s standard DriverConnectionProvider class and add the stuff i needed at the right time:
public class AuditingConnectionProvider : NHibernate.Connection.DriverConnectionProvider
{
public override IDbConnection GetConnection()
{
IDbConnection connection = base.GetConnection();
SetContextInfo(connection);
return connection;
}
public override void CloseConnection(IDbConnection connection)
{
ClearContextInfo(connection);
base.CloseConnection(connection);
}
private void SetContextInfo(IDbConnection connection)
{
// ...
}
private void ClearContextInfo(IDbConnection connection)
{
// ...
}
}
Pretty simple huh? All you have to do now is to configure NHibernate to use this new ConnectionProvider in your hibernate.cfg.xml file:
<property name="connection.provider">My.Assembly.AuditingConnectionProvider, My.Assembly</property>
Was that easy or what? If only all frameworks were extensible in such an easy manner
September 18th, 2008 at 8:53 pm
[...] Note: this was orginally posted on my own blog [...]
September 19th, 2008 at 4:24 pm
now that IS easy!
October 13th, 2008 at 1:43 pm
Well, that was easy. But how can I set the actual connection.provider programmtically? I would like to create the MyDriverConnectionProvider instance myself (or let another DI-container…) and pass the initialized instance to Nhibernate. Do you know how to do that?
October 13th, 2008 at 1:50 pm
I can’t find anything regarding a ConnectionProvider factory or anything like that, so i don’t think you can make it do what you want to do.
You could provide two constructors to achieve what you want though…
public MyProvider() : this(IoC.Resolve(typeof(IDependency1)), IoC.Resolve(typeof(IDependency2)))
{}
public MyProvider(IDependency1 dep1, IDependency2 dep2)
{
…
}
Not perfect, but if no other way exists, it’s not so bad i guess
btw, i used the Resolve(typeof())) syntax because i’m too lazy to find out how to escape the generic bracket thingies :p
October 13th, 2008 at 2:31 pm
Wow, quick reply, thanks!
Well, I think I need it the other way around: MyProvider has no external dependencies.
However I have another component (AnotherComponent) which needs the same MyProvider instance Nhibernate is using.
The MyProvider implements two interfaces:
public class MyProvider : NHibernate.Connection.DriverConnectionProvider, IAnotherInterface
AnotherComponent needs an Object of type IAnotherInterface:
public AnotherComponent(IAnotherInterface needsToBeTheSameMyProviderInstance)
If I could set an Instance to NHibernate, I could let Spring do the binding via its config for both NHibernate as well as for AnotherComponent.
Any idea or am I just missing something?
October 13th, 2008 at 2:33 pm
ah ok, i see what you mean… unfortunately, i don’t think it’s gonna be possible without an ugly hack :p
October 13th, 2008 at 2:37 pm
Ok, at least I didn’t missed some obvious thing
Thanks again for your fast reply!
March 30th, 2009 at 12:26 pm
[...] remembered a trick i had used earlier, which is to extend NHibernate’s DriverConnectionProvider. It could then set the setting with [...]