For the next rev of dashCommerce, we are going to be using NHibernate and so I have been exploring ways to both: 1.) get up to speed with NHibernate and 2.) the fastest way to get started working with NHibernate. I had seen all of the articles on Fluent NHibernate, but to me it just looked like a C# version of Xml. That’s not a ding against, it, but when you have system with about 50 tables in it, well . . . typing is typing.
But, one thing that caught my eye when I started looking around the Fluent NHibernate project was the AutoMapping feature. This feature will allow you to set up some conventions for use against your database and it will attempt to generate the mapping files for you. That’s pretty slick.
But would it work well enough to actually use since Fluent NHibernate is still pretty young?
Well, it worked well enough for me.
So, here is what I had to do to pull it off against the dashCommerce database.
When I started trying to get the mappings to work against a bunch of dashCommerce tables, I was getting some errors about not being able to map certain entities. So, as soon as I saw that, and recognized that the exception wasn’t going to help me identify what, exactly, the problem was I dug into the code and ended up changing this very simple line in the ClassMap file (public void ApplyMappings(IMappingVisitor visitor)) around line 195: Debug.WriteLine(writer.ToString()); to Console.WriteLine(writer.ToString()); I was using a small console client with some sample queries in it, so this was best for me at the time. But, once I did that, I was able to quickly look at that output and determine the cause of my pains.
To be exact, they were all related to a few key things:
- The AutoMap functionality relies on conventions to determine the structure of your database tables.
- I had to update the AutoMap conventions with the conventions used by the dashCommerce database.
- The dashCommerce database was not entirely consistent in its naming conventions. (gufaw!)
This last one is the one that really appealed to me as I know I put a lot of work into being consistent in the way the dashCommerce database is constructed, but it just showed me where I had missed things. This is great, and showed me the beauty of the AutoMap functionality. And it will be helpful in generating an upgrade script for dashCommerce going forward to ensure the database conventions are consistently applied.
So, how much code did it take to get the AutoMapping functionality working with dashCommerce? Not much. It’s not at 100% coverage yet, but we are in pretty good shape.
One other interesting thing about the AutoMapping in combination with dashCommerce is that in the dC database, we kind of namespace things out so there is a correlation between the assemblies and the database. For instance, we have the following naming conventions: dashCommerce _Core_tableName, dashCommerce_Store_tableName, and dashCommerce_Content_tableName. I’m still hmm’ing and haw’ing over whether or not I really like that anymore, but it does make things very clear for the developer that is customizing dashCommerce. That means it made the conventions less flexible, so I had to accommodate that in the code by creating separate files for each mapping. So, for instance, in getting the Core up and running, the code for Fluent NHibernate AutoMap was as simple* as this:
var configuration = MsSqlConfiguration.MsSql2005
.ConnectionString(connectionString => connectionString
.Server("MYSERVER")
.Database("DASHCOMMERCE")
.Username("USER")
.Password("PASSWORD"))
.UseReflectionOptimizer()
.ConfigureProperties(new Configuration());
var autoPersistenceModel = AutoPersistenceModel
.MapEntitiesFromAssemblyOf<Log>()
.Where(type => type.IsClass && !type.IsAbstract && type.Namespace == "Core.Entities")
.WithConvention(convention =>
{
convention.FindIdentity = p => p.Name == p.DeclaringType.Name + "Id";
convention.GetTableName = type => "dashCommerce_Core_" + type.Name;
convention.GetPrimaryKeyNameFromType = type => type.Name + "Id";
convention.GetForeignKeyNameOfParent = prop => prop.Name + "Id";
})
;
autoPersistenceModel.Configure(configuration);
*simple took me a couple of hours, but that was digging into Fluent NHibernate for the first time and trying to grok and learn all at once.
There is still some work to do on Many to Many relationships, but this was darned impressive and a huge boost in productivity for dashCommerce and NHibernate. Thank you to the folks that have created Fluent NHibernate, this makes working with NHibernate easier than any other ORM / code generation tool out there.
One other side note worth mentioning is that once you have the AutoMap set up correctly, you can have Fluent NHibernate spit out the mapping files so that you can use those directly (which is what we are doing for dashCommerce).