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]]">
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.
Just a related thought:
ReplyDeleteI 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
@jbandi is this similarly possible for the java version of hibernate?
ReplyDelete@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.
@Urs Thanks, interesting position, will have to sleep over that :-)
ReplyDelete@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.