In my current project we’re using NHibernate.Spatial against an SQL Server 2008 DB. This replaces our need to work with the cumbersome ArcSDE when writing and reading data in our applications (while still allowing ArcMap users to view the maps it holds by registering the tables in SDE). This made our life so much lovelier. We now have real domain objects to work with, and absolutely no COM is required to do stuff!
Anyway, we’re using the awesome Fluent NHibernate to map all our entities, and in order to test them, we have a base class (something like this) that all our tests use. The problem is, we want our tests to run against the in-memory SQLite database, but it doesn’t support the spatial stuff, and there is no NHibernate.Spatial dialect for it. A problem indeed – most of our code has nothing to do with geography, and it would be a damn shame if we couldn’t use an in-memory database to test it easily.
Well, we ended up using a cool feature of Fluent NHibernate, that allows us to specify conventions for our class maps. For instance, lets say we have a Country entity, which looks like this:
And the mapping for this class looks like this:
This mapping class is problematic with SQLite, as this database doesn’t support using the custom GeometryType (which implements NHibernate’s IUserType) that comes with NHibernate.Spatial. If only we could do without specifying the custom type in our mapping, and use a different one in our tests files… Oh! Fluent NHibernate conventions let us do just that. We can use two different conventions, one for SQL 2008, which we will use in our production code, and one for SQLite, which will be used in most tests. Here’s how our convention for SQLite looks like (the one for SQL 2008 is exactly the same, only uses the above GeometryType custom type):
You can see that we’re using SQLiteGeometryType. If you don’t know what that is, it’s OK. It’s our own simple implementation, as defined below:
All we do here is tell NHibernate that when it sees an IGeometry property that it should persist, it should convert it to a string and save it as varchar. It also goes the other way around. GeometryTypeBase is a helper base class that exists in NHibernate.Spatial.
Now all that is left for us is to configure NHibernate to use our convention:
And now we’re done. We can persist our spatially-enabled entities to SQLite and write tests for them. Granted, we can’t use more advanced features like spatial queries that run in the database, but most of our code doesn’t do that anyway. Having an in-memory database is perfect for testing the OR mappings and domain service operations.