NHibernate Mapping an Enum

18Apr08

Option 1 : Subclass Enummapping class

But that forces us to create several meaningless little classes just for the sake of mapping and if its always the string name of the enum why go through all that ?

Option 2 : Create a Generic Enum mapping usertype ..which might look like …

public class EnumMappingType : IEnhancedUserType , IParameterizedType
    {
        private Type enumClass;

        public  string Name
        {
            get { return "enumstring - " + enumClass.Name; }
        }

        public  Type ReturnedClass
        {
            get { return enumClass; }
        }
        public object StringToObject(string xml)
        {
            return null;
        }

        public object FromXMLString(string xml)
        {
            throw new NotImplementedException();
        }

        public string ObjectToSQLString(object value)
        {
            return GetValue(value).ToString();
        }
        public virtual object GetValue(object code)
        {
            //code is an enum instance.
            return code == null ? string.Empty : code.ToString();
        }

        public void SetParameterValues(IDictionary parameters)
        {
           enumClass = Type.GetType((string) parameters["enumClass"],true);
        }

        public  object FromStringValue(string xml)
        {
            return GetInstance(xml);
        }
        public virtual object GetInstance(object code)
        {
            //code is an named constants defined for the enumeration.
            try
            {
                return Enum.Parse(enumClass, code as string, true);
            }
            catch (ArgumentException ae)
            {
                throw new HibernateException(string.Format("Can't Parse {0} as {1}", code, enumClass.Name), ae);
            }
        }

        public  string ToString(object value)
        {
            return (value == null) ? null : GetValue(value).ToString();
        }

        public  bool Equals(object x, object y)
        {
            return (x == y) || (x != null && y != null && x.Equals(y));
        }

        public int GetHashCode(object x)
        {
            throw new NotImplementedException();
        }

        public object NullSafeGet(IDataReader rs, string[] names, object owner)
        {
            object code = rs[rs.GetOrdinal(names[0])];
            if (code == DBNull.Value || code == null)
            {
                return null;
            }
            return GetInstance(code);
        }

        public void NullSafeSet(IDbCommand cmd, object value, int index)
        {
            IDataParameter par = (IDataParameter)cmd.Parameters[index];
            if (value == null)
            {
                par.Value = DBNull.Value;
            }
            else
            {
                par.Value = Enum.Format(this.enumClass, value, "G");
            }
        }

        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[] { SqlTypeFactory.GetString(10) }; }
        }

        public Type ReturnedType
        {
            get { return enumClass; }
        }

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

And the corresponding mapping file can be ( you can also create shortcut typedef’s btw )

<property  name="EnumPropertyName">
      <column name="EnumPropertyName" sql-type="nvarchar(50)" not-null="true"/>
      <type name ="....EnumMappingType, Assembly.Name">
        <param name ="enumClass">Your.Enum.ClassName</param>
      </type>
</property>

Hope that helps someone out there !!!

Advertisements


2 Responses to “NHibernate Mapping an Enum”

  1. 1 Julian Skagen

    Nice, but I really miss the possibility to map enums to own tables (this is the way that the DBA wants it), and in addition there will be referential integrity and selecting all in a table based on an enum type will go much faster as the fk is automatically indexed.

    Cheers Julian.

  2. 2 akcoder

    Another option is to use this method my colleague figure out:
    http://orand.blogspot.com/2006/12/generic-nhibernate-enum-string-mapping.html

    Then your property in your hbm file is reduced to one line:


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: