We have been using NHibernate and using SQLite for in-memory tests which has worked very well for us but hit an issue when using schemas.
We wanted to separate out the tables used by our services through the use of schemas as schemas provides a very nice clean logical separation. However, although NHibernate supports schemas through the schema attribute on your class mappings, our SQLite tests fail as SQLite doesn’t support schemas.
We looked into ways around this. Our first port of call was to look at whether their is a way of managing this through our own NHibernate dialect class but our investigations led us to a dead end – although we plan on revisiting this later.
So we switched to looking at the SQLite ADO.NET provider. We figured that if we wrapped this then we could intercept the calls to it and override the “schema.table” requests into “schema_table”.
To achieve this we provide our own implementations of the following:
- IDbCommand
- IDbConnection
- DbParameter
- DbParameterCollection
- IDbTransaction
Within each of these implementations we wrap the underlying System.Data.SQLite versions of these to delegate down to. Within the command itself we parse the provided CommandText and detect if a schema is used, overriding this when necessary.
The final piece of the puzzle is to provide our own NHibernate driver which will tell NHibenate to use our implementation of IDbCommand. We couldn’t just inherit from the SQLite20Driver class so we had to copy its implementation as provided below:
namespace TheAgileWorkshop.SQLiteWithSchemaSupport
{
public class SQLiteDriver : ReflectionBasedDriver
{
public SQLiteDriver()
: base(
"TheAgileWorkshop.SQLiteWithSchemaSupport",
"TheAgileWorkshop.SQLiteWithSchemaSupport.SQLiteWithSchemaConnection",
"TheAgileWorkshop.SQLiteWithSchemaSupport.SQLiteWithSchemaCommand")
{
}
public override bool UseNamedPrefixInSql
{
get { return true; }
}
public override bool UseNamedPrefixInParameter
{
get { return true; }
}
public override string NamedPrefix
{
get { return "@"; }
}
public override bool SupportsMultipleOpenReaders
{
get { return false; }
}
public override bool SupportsMultipleQueries
{
get { return true; }
}
}
}
Now to use schemas with NHibernate and keep your in-memory SQLite tests passing, reference the TheAgileWorkshop.SQLiteWithSchemaSupport.dll and specify this driver class (TheAgileWorkshop.SQLiteWithSchemaSupport.SQLiteDriver) in place of the SQLite20Driver class that exists at the moment.
To use this, you can get the source or grab a copy of a release build of the dll directly.
I hope this helps others. If there are any issues then please don’t hesitate to let me know.
UPDATE: We have updated the release build dll link with a version that supports ‘.’ in the parameter values (such as a decimal property) based on MacX’s comments.
In the delivered Sources the CommandTextParser.cs-Source file is missing.
Can you provide it?
Thx
By: MacX on June 30, 2009
at 6:38 am
Thank you for pointing that out – it has now been checked in.
By: weblander on June 30, 2009
at 8:15 am
Thank you very much
By: MacX on June 30, 2009
at 8:28 am
Hi Stephen,
I discovered a little bug.
When I try to execute a native SQL-query with decimal values (like 30.1 or sth. similar) this floating point is interpreted as an underscore.
Tonight I will deliver a litte sample project, maybe including a possible solution.
Thx MacX
By: MacX on September 23, 2009
at 1:12 pm
That would be great!
If you don’t get round to providing a fix then I will look at this tonight anyway and get a solution in place, otherwise I will merge your solution in so that everyone can benefit from your work.
Cheers
+Steve
By: Stephen Oakman on September 23, 2009
at 1:47 pm
What about a google-code-repository for this little project?
By: MacX on September 23, 2009
at 2:19 pm
We’ve just added an explicit test for a decimal value but have realised that we did fix this issue but haven’t blogged about it or provided an updated zip of the dll’s. The source repository is public so you can grab the code. Svn is located at http://subversion.assembla.com/svn/TheAgileWorkshop/Examples/NHibernate/SQLiteWIthSchemaSupport
By: Stephen Oakman on September 23, 2009
at 2:44 pm