Click here to Skip to main content
15,881,413 members
Articles / Operating Systems / Windows

Working with legacy databases in NHibernate Part 2 - Fixed length strings and custom NHibernate types

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
13 Dec 2012CPOL2 min read 9.9K   4   2
Fixed length strings and custom NHibernate types.

See also Part 1 - Compound foreign keys

Simple one this but it drove me crazy for a while. For some reason *cough* incompetence *cough* the technical manager at my previous company had a penchant for using fixed-length fields for data that wasn't, um, fixed length. So if you looked through the application code you'd find .Trim() statements liberally sprinkled throughout the code, including on fields that didn't actually need them (because keeping track of those that did and those that didn't became a near-impossible task). Of course, sometimes developers forgot to trim the strings and you'd get subtle bugs from incorrect string concatenation occurring, or users would click in a text field and find themselves having to delete masses of white space to edit their text.

Putting aside the fact that we shouldn't have been using fixed-length strings in the first place, how data gets stored in the database is a persistence concern and details of this should not be allowed to leak into the application. Trimming the fields of fixed length strings should be taken care of in the data access code if necessary. When using ADO.NET directly it's relatively easy to apply this as the data is mapped into your classes, of course if you have lot's of different functions calling different stored procs it's also easy to forget to do it. In an NHibernate data-layer we don't have the same direct access to the data coming in, but thankfully it's relatively easy to get NHibernate to automatically trim any strings for us by using a custom type.

The code is pretty simple, by and large it doesn't need to do anything except return the trimmed value in the NullSafeGet function:

C#
public class TrimmedString : IUserType, IEnhancedUserType
{
    #region IUserType Members

    public object Assemble(object cached, object owner)
    {
        throw new NotImplementedException();
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Disassemble(object value)
    {
        throw new NotImplementedException();
    }

    public int GetHashCode(object x)
    {
        return x.GetHashCode();
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
    {
        object obj = NHibernateUtil.String.NullSafeGet(rs, names[0]);
        if (obj == null) return null;
        return obj.ToString().TrimEnd();
    }

    public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
    {
        if (value == null)
        {
            ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
        }
        else
        {
            ((IDataParameter)cmd.Parameters[index]).Value = value;
        }

    }

    public object Replace(object original, object target, object owner)
    {
        throw new NotImplementedException();
    }

    public Type ReturnedType
    {
        get { return typeof(string); }
    }

    public global::NHibernate.SqlTypes.SqlType[] SqlTypes
    {
        get { return new global::NHibernate.SqlTypes.SqlType[] { NHibernateUtil.String.SqlType }; }
    }

    public new bool Equals(object x, object y)
    {
        if (object.ReferenceEquals(x, y)) return true;
        if (x == null || y == null) return false;
        return x.Equals(y);
    }

    #endregion

    #region IEnhancedUserType Members

    public object FromXMLString(string xml)
    {
        return xml;
    }

    public string ObjectToSQLString(object value)
    {
        return value.ToString();
    }

    public string ToXMLString(object value)
    {
        return value.ToString();
    }

    #endregion
}

Then in the .hbm mapping, set the type of the field to be our new type:

XML
<property name="Title" column="ctitle" access="property" type="TrimmedString" />

Now the field will be automatically trimmed as NHibernate reads it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) AJ Systems
United Kingdom United Kingdom
I am currently a developer at a management consultancy company.
In addition to all things .NET I have a keen interest in Japan and the Japanese language and hope to be able to combine these passions one day soon.

Comments and Discussions

 
SuggestionLink to Part 1??? Pin
Klaus Luedenscheidt6-Dec-12 19:12
Klaus Luedenscheidt6-Dec-12 19:12 
GeneralRe: Link to Part 1??? Pin
Pete Sutcliffe12-Dec-12 22:44
Pete Sutcliffe12-Dec-12 22:44 
Good idea, I've added it now thanks.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.