Thursday, April 22, 2010

.Net QuickTip: Persisting enums as strings with NHibernate

Scenario: You want to map the values of an enum-typed property of an entity as a string into the database with NHibernate.

Solution: NHibernate stores enums with their numeric value into the database as default.
In order to save the value as string, you have to use the type attribute of the property element in the xml-mapping.
As of NHibernate 2.1 you can use the type NHibernate.Type.EnumStringType<T> like this:

<property column="DataProviderConst" name="DataProvider"
   type="EnumStringType`1[[My.Namespace.DataProvider, My.Namespace]]">
(note the strange syntax to declare the generic type)

On the web there are floating a lot of articles around, telling that you have to create a derived Type of NHibernate.Type.EnumStringType for each enum, or generate a generic EnumMapper type.
This is not necessary since NH 2.1. This post finally enlightened me.

In Fluent NHibernate mapping enums to strings is the default. You don't have to do anything.
Now, if mapping enums to strings is a best practice or an antipattern is a whole different question.

3 comments:

  1. Just a related thought:
    I wouldn't store enums in the database. The risk of a braking change in a follow-up version is just too great. Saving as strings is surely better than saving as int, but I suggest to abandon enums completely (when persisted) and choose simple constants. Note that enums are NOT constants. It is just too simple to make a mess by introducing or deleting a value changing all others. Yes I know that you can set a value per enum value, but then a set of constants is even simpler ;-)
    Extensibility is another problem inherent in enums (see point 3 in http://www.planetgeek.ch/2009/02/07/top-10-of-software-design-evilness/)

    Fight the enums :-D

    Cheers,
    Urs

    ReplyDelete
  2. @jbandi is this similarly possible for the java version of hibernate?

    @urs probably you are lucky your enum breaks and you notice your inconistency rather early in the change process. If you consider an enum as the set of values for a very specific issue that your application currently supports, I see no point of not using them. On the other hand, the implementation of enums in Java is rather poor, mainly because of the poor implementation of class members in Java. Thus there may be reasons not to use them.

    ReplyDelete
  3. @Urs Thanks, interesting position, will have to sleep over that :-)

    @bertolami in JPA its actually much easier:
    Mapping enums with attributes is done like this:

    @Enumerated(EnumType.STRING)
    private Rating rating;

    Where EnumType can be STRING or ORDINAL.
    (probably there is an equivalence to do it in xml)

    Last time I checked plain Hibernate you still had to write a custom user type:
    http://community.jboss.org/wiki/Java5EnumUserType

    Enums are actually one of the few language things I like better in Java than in .Net...
    In Java, enums are full fledged named instances of a type, while in c# enums are basically named constants.

    ReplyDelete

Related Posts Plugin for WordPress, Blogger...