One of the new projects at my day job is using ActiveRecord for data access. I’m a huge fan of ActiveRecord (and of all things Castle), but I like the fact that LINQ makes it very easy to do ad-hoc queries with a compile-time safety net. Unfortunately, ActiveRecord does not support LINQ out of the box. Luckily though, ActiveRecord is built on top of NHibernate, and LINQ support is available via NHibernate Contrib, at least if you aren’t afraid to venture into the source. If you follow the steps below, you can build your own LINQ provider for ActiveRecord and get the syntactical sugar of language-integrated query with the simplicity of ActiveRecord. Note that you will need to know the basics of using Subversion in order to follow these steps (I highly recommend TortoiseSVN), and you must have NAnt installed and in working order.
- Checkout NHibernate.LINQ from https://nhcontrib.svn.sourceforge.net/svnroot/nhcontrib/trunk/src/NHibernate.Linq.
- Checkout Castle from http://svn.castleproject.org:8080/svn/castle/trunk.
- Copy NHibernate.dll from "NHibernate.Linq\lib" to "Castle\SharedLibs\net\2.0". This is necessary because the latest release build of NHibernate doesn’t work with NHibernate.LINQ. You could try to build NHibernate from its trunk and copy the DLL to both Castle and NHibernate.LINQ, but since the projects occasionally end up out-of-sync, I prefer the copy-and-paste method.
- Build Castle using NAnt by running this command in the root of your Castle checkout: nant rebuild -D:common.testrunner.enabled=false. Do *NOT* try to build using the solution; the NAnt scripts create some of the required AssemblyInfo files, and you can’t build without those.
- Copy the following DLLs from the Castle build output to "NHibernate.Linq\lib": Castle.Core.dll, Castle.DynamicProxy2.dll, Iesi.Collections.dll.
- Build NHibernate.Linq using MSBuild, Visual Studio, or whatever you want.
- That’s it (sort-of).
- (Recommended) I like to copy the required DLLs to a common folder that I keep under version control with my project. This insures that nothing gets lost since I’m lazy and really don’t want to jump through these hoops more often than absolutely necessary. If you go that route, copy the following DLLs from the various build output directories to a common folder: Castle.ActiveRecord.dll, Castle.Components.Validator.dll, Castle.Core.dll, Castle.DynamicProxy.dll, Iesi.Collections.dll, NHibernate.dll, and NHibernate.Linq.dll.
At this point, you should now have Castle, NHibernate, and NHibernate.LINQ all synced up where they can play together. All that remains is to create our ActiveRecord LINQ context. So, let’s begin!
- Create a new class library in Visual Studio.
- Add references to the DLL’s listed in the optional step 8 above. If you didn’t copy things to a central folder, you probably will do so now. :)
- Create a new class named ActiveRecordLinqContext. Go ahead and create a corresponding test fixture class now as well (you *do* practice unit testing, right??)
A quick note: I’m using SQLite for my tests. If you go that route, be sure you place the SQLite DLL where NHibernate can find it. Alternatively, you can test with any other database that NHibernate supports. A future post will detail how to use SQLite for clean and simple ActiveRecord testing.
That’s it for the boring stuff, on to the glorious code!
That’s pretty simple, but how do we use it? Here’s the test fixture and a test class:
Run the tests, and you should see green. You can turn on logging (by calling log4net.Config.BasicConfigurator.Configure()) if you want to see the raw SQL being sent to the database to confirm that LINQ is working.
Big, big props go out to Ken Egozi; his post got me on the right track to get all this working.