Using an enum on a FluentNHibernate mapping [C#]

One of these days I needed to map a C# class to a database table using FluentNHibernate. So far so good….
But then I got stuck as one the class properties was an enum.

As it turns out, there is no automatic mapping to enums.

The solution is to use a Custom Type and let FluentNHibernate know that that specific property has a custom type.
How can that be achieved?


Let’s think of an enum that represents a project type. This enum has two possible values: WebProject, referenced as ‘W’ on the database and DesktopProject, referenced as ‘D’ on the database.

Now the code:

The enum:

public enum ProjectType
{
    WebProject,
    DesktopProject
}

Now, to create the custom type you need to implement the FluentNHibernate’s IUserType Interface.
The methods that really matters to this issue are “NullSafeGet”, which converts the text into an enum value , “NullSafeSet” which does the opposite and “ReturnedType” in order to return the object type of your enum.


The Code:

using System;
using System.Data;
using NHibernate.SqlTypes;
using NHibernate.UserTypes;



namespace YourNamespace.Persistence.Mappings.CustomTypes
{

   public class ProjectTypeMap : IUserType
   {

       new public bool Equals(object x, object y)
       {
           return object.Equals(x, y);
       }

       public int GetHashCode(object x)
       {
           return x.GetHashCode();
       }

       public object NullSafeGet(IDataReader rs, string[] names, object owner)
       {
           object r = rs[names[0]];
           var value = (string)r;

           if (string.IsNullOrEmpty(value))
               throw new Exception("Invalid Status");

           switch (value)
           {
               case "W":
                   return ProjectType.WebProject;
               case "D":
                   return ProjectType.DesktopProject;
               
               default:
                  throw new Exception("Invalid Project Type");

           }


       }

       public void NullSafeSet(IDbCommand cmd, object value, int index)
       {
           object paramVal = 0;
           switch ((ProjectType)value)
           {
              
               case ProjectType.WebProject: paramVal =
"W"; break;
	       case ProjectType.DesktopProject: paramVal =
"D"; break;
               default:
                   throw new Exception("Invalid Project Type");
           }
           var parameter = (IDataParameter)cmd.Parameters[index];
           parameter.Value = paramVal;
       }

       public object DeepCopy(object value)
       {
           return value;
       }

       public object Replace(object original, object target, object owner)
       {
           return original;
       }

       public object Assemble(object cached, object owner)
       {
           return cached;
       }

       public object Disassemble(object value)
       {
           return value;
       }

       public SqlType[] SqlTypes
       {
           get { return new SqlType[] { new StringSqlType() }; }
       }

       public Type ReturnedType
       {
           get { return typeof(ProjectType); }
       }

       public bool IsMutable
       {
           get { return false; }
       }
   }
}

Now all that’s left is the FluentNHibernate Mapping:

public class ProjectMap:ClassMap<Project>
{

...
	
	//NHibernate 2.X
	Map(x=>x.ProjectType).CustomType<ProjectTypeMap>();
	
	//NHibernate 3.X
	Map(x=>x.ProjectType).CustomTypeIs<ProjectTypeMap>();
...	
}

Well, thats it. That’s how it’s done.

One thought on “Using an enum on a FluentNHibernate mapping [C#]”

  1. Fantastic post, it was exactly what I was looking for.

    I had to add the attribute Serializable on my class because it failed on NHibernate session.

    [Serializable]
    public class ProjectTypeMap : IUserType

    All good now. :)

    Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA Image

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>