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:
Be First to Comment