Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

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

, 13 Dec 2012
Rate this:
Please Sign up or sign in to vote.
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:

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:

<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)

Share

About the Author

Pete Sutcliffe
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??? PinmemberKlaus Luedenscheidt6-Dec-12 19:12 
GeneralRe: Link to Part 1??? PinmemberPete Sutcliffe12-Dec-12 22:44 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 13 Dec 2012
Article Copyright 2012 by Pete Sutcliffe
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid