Wednesday, October 12, 2005

NHibernate Update

First off, start with a small data model. Get that working, then add in other related chunks. This will save you many headaches while you get NHibernate’s complex mapping properly created.

The project I’m working on has a moderately complex data model:

12 tables, 11 of which have various relationships. NHibernate requires that you have all dependent relationships mapped out before it will work properly. This means you can’t just wire up a few of these entities, say Person, PersonType, and PersonTypeLink, and press on. You need to get <bag> or <set> elements defined in your maps for all relationships, not just the ones you’re interested in.

I’m most of the way through getting all entities mapped; however, if I had to do it over again, I’d literally drop tables I wasn’t concerned with, get maps and tests running on a subset, then proceed with wiring in other related tables. For example, following on the group I listed above (Person, PersonType, and PersonTypeLink), I’d drop everything else, get maps and tests working on those three. Then I might add in Post and PostType, followed by Subscription, SubscriptionLink, and SubscriptionFormat. Next would come Location, Event, and Attendance. Then I’d have Newsletter as the last table — an easy one with no links as dessert.

In one sense, this is sort of what I’ve done. I went so far as to create another database and built in tables one by one with the appropriate references (but none of the “fluff” fields), then I used ObjectMapper to generate classes and NHibernate’s mapping XML. This let me check what I was getting from ObjectMapper when reverse-engineering my existing table and classes. (ObjectMapper calls that “syncronization.”)

Two more semi-major modifications have to happen to my business entities:

1) I have to add members to store other business entities for tracking relationships (one-to-many, many-to-many). NHibernate works with both a Parent and Child object at the same time, so it gets/sets them via a Property. I really didn’t want to add this weight to my business entities, plus this ties the entities somewhat to NHibernate’s concept of operations.

2) I have to implement GetHashCode() for all my business entities, or at least any entity based on a link table with composite IDs. NHibernate needs GetHashCode() for its various Dictionary and List functions. Implementing GetHashCode() is fraught with peril, and I’ll have to carefully think how to get this done correctly. (Read Wagner’s Effective C# for problems with GetHashCode().) I’m not looking forward to this because it’s a difficult piece of work and it looks like it’s a showstopper until I get it done right. Bother.

One of the most irritating things about NHibernate has been some less than clear error messages. I beat my head on the table for a few hours trying to figure out why a completely sane map file was generating schema errors telling me that the <id> element wasn’t a valid child of the <class> element, and that a <discriminator> element was expected. (Discriminator elements let NHibernate, well, discriminate between different types of an entity, such as when you’ve got a Person table which holds Professor and Student entities, but is keyed off of a PersonType field. See Justin Gehtland’s article on the ServerSide for details.) My Person table didn’t store different types of Person entities, it just referenced a link table to store that information — and I’d already mapped that table. Those schema errors finally cleared up when I got all inter-related tables mapped, so it wasn’t really a schema issue, it was one entity missing dependent relationships. Arrggghhh.

I like NHibernate’s concept, and I like the clarity of its use once you’re past the initial stages. Setup and knowledge building stinks, though. I’m nearly done with this mapping (finally!), and I’m looking forward to pressing on with getting some actual implementation done on my system.

Now Playing: The Killers — Hot Fuss. Nice stuff, funky sound, good beat. No clue what they’re singing half the time, though. Hopefully they’re not singing the praises of Howard Dean, Ann Coulter, or some similar idiot. <shudder>

No comments:

About Me

I'm the owner/principal of Guidepost Systems. I help lots of great folks figure out what works and what doesn't in the world of delivering quality software -- something I'm very passionate about. I'm also a Father trying to remain sane while trying to build great software, herd my kids around, fix school lunches and handle the yardwork. (And roast great coffee!)