Yesterday at the Alt.Net tools night I gave a short talk about how to get started with NHibernate. “Getting started” means we’re talking about Greenfield project, heavily favoring Conventions (and automappings) over Configuration, and not having to mess with existing, untouchable codebase or DB schema.
The weird part was sitting there, after having used NH, a 5 year-old project, for about a week, and across the table sat Ayende, one of the main contributors to NH (and author of NHProf). Most of the time he wasn’t throwing heavy items at me, so I called that session a success.
The goal of the demo was to make this integration test pass:
(The test was created in exactly three seconds using QuickUnit. Try it out.)
I won’t re-run all the “run test, fix error” iterations here, just review the concepts and show the outcome.
DB config Issues:
- We want the test to pass as easily as possible, have no side effects, and require minimal setup costs – so we’ve used SQLite in-memory DB, using System.Data.Sqlite (free). The single DLL is the ADO.NET adapter AND the actual DB.
- Standard configuration of in-memory SQLite kills the DB after every session closes, so we needed a different connection string.
- Since we’re creating a new DB every test – we need to create the DB schema every time, using the SchemaExport tool. (More)
- Make sure the reference to System.Data.Sqlite has the “Copy local = true” flag (as it is not a completely managed dll, and does not default to true).
- Also watch out for 64bit issues and FW4.0 issues with System.Data.Sqlite.
- We desperately want to use FluentNHibernates’ automapping, so we provide an assembly to scan for entities, and a minimal adaptation of the DefaultAutomappingConfiguration object (I’ve chose to use attributes to mark persisted types. Inheritance can do just the same).
- Every entity needs a primary key in RDBMS. So we’ve added the Id property on MyEntity.
- NH wants to provide you with lazy loading for your data, so it needs to override your properties (creating dynamic proxies at runtime), so you need to make them virtual (and add a reference to the NHibernate.ByteCode.Castle assembly)
NHibernate usage issues:
- An ISession object is lightweight (and can be thought of as “Cache Scope”). Create one when it’s a logical thing to do.
- An ISessionFactory object is VERY heavyweight. Create and save it.
- Always open (and commit) a transaction (saving OR loading).
- The three main query mechanisms for NH are HQL, ICriteria and Linq2NH. I find it silly that in 2010 I won’t use linq to express my queries, so (for NH 2.1.2 only) you need to add the NHibernate.Linq.dll. NH v3.0 incorporated that syntax in the core.
- Make sure you add the required references above to the tests project, so that NHibernate can, at runtime, use all those assemblies required.
I’ve even added line count to show how 93 lines of code can create a (simple) persistence layer. It was fun.