Skip to content

USING AN ENUM ON A FLUENTNHIBERNATE MAPPING [C#]

I recently 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.

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>();
...
}

Related:

How to extend enums in C#

Published in.NETBackendDatabases

Be First to Comment

Leave a Reply