Update: I failed to realized that the functionality of converting “Y” or “N” to a boolean is already built into NHibernate by doing type=”YesNo” (see comments). I’ll leave this post up just for the academics of creating a IUserType. Go figure that I would come up with something that’s built in!
We have some legacy data where boolean values are stored as strings. “Y” is true and “N” is no. We’re also creating entities which have properties that map to this data. It would be just plain evil to have to create all the boolean properties as strings! We previously solved this problem by creating our own .NET type that had a string property for the “Y” or “N” value. This type had an implicit cast defined as a bool, so we could treat it as a boolean in expressions and assignments. We mapped this in NHibernate as a component with the single string property and this worked pretty well, but I suspected that there was a better way. Today I bought the e-book version of NHibernate in Action and quickly read through the section on creating an implementation of IUserType. I then came up with the following class that allows me to keep my types as true booleans in the code.
public class YesNoType : IUserType { public bool IsMutable { get { return false; } } public Type ReturnedType { get { return typeof(YesNoType); } } public SqlType[] SqlTypes { get { return new[]{NHibernateUtil.String.SqlType}; } } public object NullSafeGet(IDataReader rs, string[] names, object owner) { var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]); if(obj == null ) return null; var yesNo = (string) obj; if( yesNo != "Y" && yesNo != "N" ) throw new YourException("Expected data to be 'Y' or 'N' but was '{0}'.", yesNo); return yesNo == "Y"; } public void NullSafeSet(IDbCommand cmd, object value, int index) { if(value == null) { ((IDataParameter) cmd.Parameters[index]).Value = DBNull.Value; } else { var yes = (bool) value; ((IDataParameter)cmd.Parameters[index]).Value = yes ? "Y" : "N"; } } 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 new bool Equals(object x, object y) { if( ReferenceEquals(x,y) ) return true; if( x == null || y == null ) return false; return x.Equals(y); } public int GetHashCode(object x) { return x == null ? typeof(bool).GetHashCode() + 473 : x.GetHashCode(); } }
The mapping looks something like:
<property name="Active" type="NHTypes.YesNoType, NHTypes" column="ACTIVE_YN" not-null="false" />
I’m not going to go into detail and explain what all the parts are and do (see link), but I thought that I would share the class. Please let me know if you spot any problems.
Post Footer automatically generated by Add Post Footer Plugin for wordpress.

Once you have created this user type and reference it in your Domain model, is there any way to not have a reference to NHibernate in the Domain model?
I’ve done something similar (created a user type for the version column to allow mapping of a SQL Server rowversion column to something other than Byte[]). It works fine, but I feel “dirty” seeing that reference to NHibernate in the model.
Do I need to just get over it?
Thanks,
Ken Scott
@Ken – that’s the cool thing about this. My domain doesn’t reference my YesNoType. It my domain, I use plain old booleans. It might be less confusing if I had named this class YesNoMapper. It’s used for translating the database types, to .NET types. The .NET type can be anything you want as long as you supply the logic here to translate it.
So, the classes that you have talking directly to NHibernate are just a form of mapper or DTO class? Interesting…
How much churn do you have in your model that forces you to update the intermediate layer and/or the database? Do you have some sort of reflection/code generation to create an entity class from a DTO and vice versa?
@Ken – I think we’re talking about two different things.
In my entity I may have a property like
public bool Active { get; set; }
In the database, the column is a string (because it’s legacy). My custom IUserType only shows up in the NH mapping and no where else. NH invokes it for me. It expects a string to come out of the database and then converts it to a bool (and vise versa going the other way). This all happens under the hood and my domain classes never know that it’s stored as a string in the database.
I’m going to post another example which might clear things up a bit.
This is already built into NHibernate.. do type=YesNo
http://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html_single/#mapping-types-basictypes
@Matt – dang! How did I miss that? Anyway, thanks for pointing that out.
Just spotted this post. I have a similar problem and this solution does not seem directly applicable. I am from Denmark which means that instead of using Y/N in the database my predecessors opted for J/N. Can I somehow still use type=”YesNo” or do I have to use your YesNoType class?
Cool, glad I found this article Ray, I was just trying to do a wierd date conversion from our DB, I think this approach is what I’m looking for.
Pingback: FluentNhibernate: map byte enum as char | trouble86.com