Tuesday, October 18, 2011

Mapping collection of strings as nvarchar(max) using FluentNHibernate

The main feature of FluentNHibernate that seems to simplify user experience with NHibernate is its easily chainable, fluent API. But when we want something more complex, we may find it quite surprising.

One of the most common examples of non-default mapping of a property is when we need to change the column size for string property. By default, string properties are mapped tonvarchar(255) or so. We very often need to handle longer strings, too. For single string property, the way to do it is quite strange, but easy:

Map(x => x.Name).Length(4001);

I use SQL Server's magic number 4001 here - column can't be that long and column generated in the database is actually nvarchar(max). The situation gets complicated when we have a collection of strings and we want to keep those strings in the table with nvarchar(max) column named Value. It seems it should go like this:

HasMany(x => x.Names).Element("Value", x => x.Length(4001));

Second lambda parameter in Element method is to provide custom element mapping - sounds like exactly what we want. But no - it has no effect and generated schema still contains column of default length.

To achieve this pretty simple task, I needed to map it like this:

HasMany(x => x.Names).Element("Value", x => x.Columns.Single().Length = 4001);

So this is where FluentNHibernate's fluent API ends. I'm not an XML configuration fan, but using XML it will be obvious how to do this mapping. In Fluent though, it took me some time to figure it out.

1 comment:

  1. Thank you for posting this information. I realize it was a while ago but the final method doesn't work. I keep getting the following error:
    Error 69 Property or indexer 'FluentNHibernate.MappingModel.ColumnMapping.Length' cannot be assigned to -- it is read only