I am trying to map a table frp, a SQL Server 2005 DB to a class which contains an enum:
public class MyClass{
private YesNoOptional addressSetting;
public YesNoOptional AddressSetting{
{get; set;}
}
}
public enum YesNoOptional {
Yes,
No,
Optional
}
This will dictate that one of three values is inserted into the corresponding column – ‘Y’, ‘N’, ‘O’. This column is of type nchar(1).
My mapping file is like so (addressSetting is the property which is causing the problem):
<class name="IncidentDefinition" table="IR_INCIDENT_DEF" lazy="false" >
<id name="Guid" column="INT_GUID" >
<generator class="guid"></generator>
</id>
<property name="Reference" column="INT_REF" ></property>
<property name="Description" column="INT_DESCRIPTION" ></property>
<property name="AddressSetting" column="INT_ADDRESS_REQ" ></property>
<property name="Active" column="INT_ACTIVE" type="YesNo"></property>
<property name="PinDocId" column="INT_PIN_DOC_ID"></property>
</class>
Using the config above I get the following error:
NHibernate.ADOException: could not initialize a collection: System.FormatException: Input string was not in a correct format..
If I try to map the enum using a custom type like so:
<property name="AddressSetting" column="INT_ADDRESS_REQ" type="ML.Types.YesNoOptional, ML.Types" ></property>
Error: System.FormatException: Input string was not in a correct format.
Next, if I try using a specific type like so:
<property name="AddressSetting" column="INT_ADDRESS_REQ" type="String" ></property>
This error is generated: NHibernate.PropertyAccessException: The type System.String can not be assigned to a property of type System.ArgumentException: Object of type ‘System.String’ cannot be converted to type ‘ML.Types.YesNoOptional’..
As a last resort I tried to specify the type as a char like so:
<property name="AddressSetting" column="INT_ADDRESS_REQ" type="Char" ></property>
This works a bit better, as it in it doesnt throw an error, however instead of returning the character from the table and mapping it to the enumerated type the ASCII value of the character is returned instead – so Y is represented by 89!
I am hoping someone can explain what I am doing wrong and\or how why this is happening please?
Thanks
Morris
You might consider creating a custom IUserType for this. I wrote a blog post about doing something similar with DateTime, and you could copy+paste 90% of the code: http://blog.statichippo.com/archive/2010/01/07/calendar-sizes-datetime-vs-nullable-sqldatetime-in-nhibernate.aspx
Basically, the biggest changes are in NullSafeSet and NullSafeGet. In the NullSafeSet you’ll want to do a switch on your enum and then set the DB value to Y/N/O accordingly. And in your NullSafeGet you’ll want to do a switch on the result (probably not a bad idea to run Char.ToLower() first) and return the corresponding enum.
Simple, powerful, and it doesn’t hack your model to work with your DB.