Wednesday, January 06, 2010

Custom column names in Fluent NHibernate

In working on our web application, I came across an interesting issue with our Fluent NHibernate mapping files. On property mappings where we specified a column name (using the .Column("columnName") property), all of the other attributes that we applied to the property (length, nullability, lazyloading, etc) were ignored. This has been documented in here. I needed to move forward with this, so I wrote a simple extension method to handle our scenario.

This extension method is used in place of the Column("columnName") method call and doesn't replace the other values. Instead, it uses reflection to update the defaultColumn field's name value, just as the Length(), Nullable() and other methods do.

public static PropertyPart ColumnName(this PropertyPart part, string columnName)
        {
            const BindingFlags accessor = BindingFlags.NonPublic | BindingFlags.Instance;

            // retrieve the defaultColumn field property
            var defaultColumnField = 
                typeof(PropertyPart).GetField("defaultColumn", accessor);

            // get the current value of the field
            var defaultColumn = (ColumnMapping)defaultColumnField.GetValue(part);
            
            // set the column name as appropriate
            defaultColumn.Name = columnName;

            // reset the default column with the applied column name
            defaultColumnField.SetValue(part, defaultColumn);

            return part;
        }

I am still not sure why the Fluent guys decided to update the column name property the way that they did, but this seems to do the trick for us. As a result, I have replaced all Column() calls with ColumnName() calls, to prevent these unexpected behaviors in the future.

One risk with this solution, and it is considerable, is that I am binding to the internals of the PropertyPart class, which is subject to change out from under me.

Now, I just need to make sure I investigate the source before deploying a new build to ensure that this won't break my workaround.

What do you think?

1 comment:

  1. It looks like James Gregory has been busy and got a fix in the master repository yesterday. However, I think we will stay with my workaround until we are ready to upgrade NHibernate versions (we are still on 2.1.0.4000).

    ReplyDelete