Non-random thoughts.

2007-08-11

NHibernate enum to char(1)

For a new project we are using NHibernate to implement database persistance. Today I ran into an issue with persisting enum's. By default, NHibernate uses type in the database and the enum's underlying type, in order to generate values. For example a simple enum like this:


public enum CoffeType
{
Sugar,
NoSugar
}

with this mapping file:

<property column="CoffeType" type="Business.Entities.CoffeType, Business.Core" name="CoffeType" null="true">

and a column in the database of type integer means that Sugar becomes 0 and NoSugar becomes 1. This is all fine, and works without problems at all. However, I wanted to use predetermined values for the enums, like this:


public enum CoffeType
{
Sugar = 'S',
NoSugar = 'N'
}


I changed the type in the database from integer to Char(1). This made NHibernate puke when inserting data. After digging into the generated sql-statements, it turned out that NHibernate choose to convert my enum-values into "Sugar" and "NoSugar" instead of 'S' and 'N'. This is probably due to recognizing any Char-type in the database as a String-datatype in .NET, and converting the enum's appropriately.

A few minutes of searching the net turned up the following post:

http://blog.bittercoder.com/CategoryView,category,NHibernate.aspx

.. which solved the exact same problem, with Castle's ActiveRecord instead of NHibernate. It turns out that the solution is called NHibernate User Types. This is what I ended up with in the mapping-file:

<property column="CoffeType" type="Business.Entities.CoffeTypeType, Business.Core" name="CoffeType" null="true" />

and this is the corresponding C#-class:


public class CoffeTypeType : NHibernate.Type.PersistentEnumType
{
public CoffeTypeType()
: base(typeof(CoffeType))
{
}

public override object GetValue(object code)
{
return Convert.ToChar(code);
}

public override object GetInstance(object code)
{
return (CoffeType) Enum.ToObject(typeof(CoffeType), (Byte) ((Char) GetValue(code)));
}

public override void Set(IDbCommand cmd, object value, int index)
{
IDataParameter par = (IDataParameter)cmd.Parameters[index];
par.DbType = DbType.StringFixedLength;

if (value == null) {
par.Value = DBNull.Value;
}
else {
par.Value = GetValue(value);
}
}

public new static SqlType GetUnderlyingSqlType(System.Type enumClass)
{
if (Enum.GetUnderlyingType(enumClass).FullName == "System.Char") {
return NHibernate.SqlTypes.SqlTypeFactory.GetString(1);
}
else {
return NHibernate.Type.PersistentEnumType.GetUnderlyingSqlType(enumClass);
}
}
}


This is the way to make NHibernate map an enum property to char(1) database field.

2007-04-06

First post!

Jaha, då har man skaffat sig en blogg då. Den här utrymmet på webben är tänkt att fungera som mitt andningshål ut mot omvärlden, helt enkelt ett sätt att försäkra sig om att samtida medmänniskor inte riskerar gå miste om min ofantliga intellektuella rikedom.

Namnet på bloggen? Radioskugga är/var en teve-serie med Figge Norling i huvudrollen, som jag och min mellanbror såg på med stort nöje någongång i mitten på 90-talet. Tyvärr verkar den inte komma i repris, men man kan ju alltid hoppas.

Vi får väl ser hurpass väluppdaterad den här bloggen egentligen blir, men jag ska verkligen försöka tänka på alla er hängivna fans där ute, om skrivarglöden skulle börja falna.