"NHibernate: have I told you today how much I love you?"
The other day I had a good reason to use a generic dictionary and I though hey, I wonder how I'll get that working with NHibernate... It's very simple to persist Generic Dictionarys with NHibernate as I found out. Let's see an example...
.NET PSEUDO CODE
Take a person and his favorite or least favorite deserts:
First we have a Person object
class Person
{
int PersonId;
string FirstName;
string LastName;
}
class Desert
{
int DesertId;
string Name;
}
Now we want to associate a Person with all the deserts and rate how much he likes them (I know, it's contrived, but it's simpler than the business case I did this with yesterday). So first we might create an enum for storing how one feels about a particular dessert (we'll call it Rating):
enum Rating
{
Love,
Like,
Impartial,
Dislike,
Disdain
}
And then we might add a generic dictionary to the Person object like so:
class Person
{
string FirstName;
string LastName;
Dictionary<Desert, Rating> DesertRatings;
}
Looks good. Now how would we use NHibernate to persist this? First off, let's make a slight change to the Person object because NHibernate actually uses IDictionary, so that last line of the Person object would look more like:
IDictionary<Desert, Rating> DesertRatings
DATABASE TABLES
To persist this data we first create the tables in our database. Assuming we used the code above, I would probably create 3 different tables: 1 to store the Persons, 1 to store Deserts, and 1 to store the association between Persons and their Desert ratings. The tables might look like this:
PEOPLE * PersonId, int * FirstName, varchar * LastName, varchar
DESERTS * DesertId, int * Name, varchar
PEOPLEDESERTRATINGS (PersonId and DesertId will be the primary keys since 1 person can only have 1 rating for a specific desert) * PersonId, int * DesertId, int * Rating, int (this will store the integer representation of the enum)
NHibernate Mappings
Now behold the magic of NHibernate. Let's take a look at what the Person.hbm.xml file might look like:
<?xml version=”1.0″ encoding=”utf-8″ ?>
<hibernate-mapping xmlns=”urn:nhibernate-mapping-2.2″ assembly=”MyAssembly” namespace=MyNamespace”>
<class name=”Person” table=”People”>
<id name=”PersonId” column=”PersonId” type=”Int32″ unsaved-value=”0″>
<generator class=”native”></generator>
</id>
<property name=”FirstName” column=”FirstName” type=”String” not-null=”true” />
<property name=”LastName” column=”LastName” type=”String” not-null=”true” />
<map name=”DesertRatings” table=”PeopleDesertRatings”>
<key column=”PersonId” />
<index-many-to-many class=”Desert” column=”DesertId” />
<element column=”Rating” type=”MyNamespace.Rating” not-null=”true” />
</map>
</class>
</hibernate-mapping>
That's all there is too it. There's a lot that I didn't cover here, and this is NOT meant to be a tutorial on how to design your objects or tables. However, I think I've shown how amazingly easy it is to persist this kind of thing using NHibernate. I didn't find anything online about this before I tried it and it worked the first time, but I would have felt more comfortable trying it had I seen someone else do it first. So hopefully this post helps someone feel comfortable diving right in.