NHibernate Best Practice: Avoid using CHAR/NCHAR columns as discriminators

time to read 2 min | 344 words

One of the things that I do is provide NHibernate support for some of our clients. This gives me the chance to see NHibernate used in many different scenarios.

A few days ago I got a call, they couldn't get discriminator values to work with NHibernate. That was very surprising, since I worked with them before, and they are well tested code. After looking at the code and the mapping, I was still at a loss. Everything looked fine, I couldn't figure out what was happening. I still got "WrongClassException: Object with id: 1 was not of the specified sublcass: Foo (Discriminator: Bar    )"

I pulled the big guns and loaded NHibernate's sources and started debugging, and then it became immediately clear what the issue was. The discriminator values for this class were "Foo" and "Bar", but the discriminator value from the database was "Bar  ". Notice the extra spaces.

A quick look at the schema showed that the discriminator column was defined as NCHAR(5), which meant that any value less than 5 characters would be padded. Changing that column to NVARCHAR solved the issue.

In general, I would recommend to use integers as discriminator columns, and use a lookup table (with FK!) to handle the human readable values. Not only does this allow to easily check what type is each row, but it is faster to load (less data travels on the wire) and safer from whitespace / enconding / capitilization issues.

While I admit that I have not met someone trying to use Hebrew characters as discriminator values, I'm sure that the only thing that protects us from that is that the guys who thinks Taarich* is a good name for a column are still busy learning just how much damage they can cause with datasets.

* Taarich - one of many ways to write Date in Hebrew in English. If the last statement didn't make any sense, don't worry, it shouldn't.