Fluent NHIbernate automapping of List<string>?
Asked Answered
R

3

12

Fluent NHibernate doesn't like this, throwing an error:

{"Association references unmapped class: System.String"}

OK fine, I can see why this would cause a problem - but what's the best solution?

I don't really want it to store a delimited list of strings in a single field, this would get ugly if my list contains many strings.

I also don't really want a table 'string', for obvious reasons.

I guess I can solve this by wrapping my List<string> inside a class, but this feels a little heavyweight. I'm starting to think its the best solution though.

What's the best way to get Fluent NHibernate to handle this?

I totally expect these values to be stored in another table. I thought perhaps that I may have been able to setup some automapping convention that instructs NHibernate 'If you see a class X that contains List<*some primitive type*>, then go ahead and automatically create a reference table that maps to this collection.

It feels a bit heavy to go and wrap every single collection in a class. If that is the best solution however, then so be it.

Remunerative answered 21/12, 2009 at 19:13 Comment(4)
if you don't want it as a delimited string in a single field, and you don't want it in another table, then where? this is still a relational database...Subgroup
I'm not bothered by how the relational database handles this. I'm wondering how I can get the automapping to infer this is what I want to do for all string lists in my domain model.Remunerative
@Remunerative - as far as I know, there's no way to tell Fluent NHibernate how to map ALL lists of strings. The solution I provide in my answer requires an override for each list of strings in your domain model. It's only a couple of lines of code for each override, so it's not too bad...Karren
I come across this today and found a simpler solution (Region with a list of country codes): HasMany(x => x.Countries).KeyColumn("CNTRY_REGION_CD").Element("value");Curtcurtail
K
7

I had this exact same issue a few weeks back, with floats instead of strings.

how-do-you-automap-listfloat-or-float-with-fluent-nhibernate

It turns out that Automapping does not work with primitive types.

Edit - This is no longer true - the FNH team has fixed the problem

There's a lot of sample code in the accepted answer to my question, but the key point is to add an override for your lists of primitive types ("RawY" in the example below):

public class DlsAppOverlordExportRunData
{
    public virtual int Id { get; set; }
    // Note: List<float> needs overrides in order to be mapped by NHibernate.
    // See class DlsAppOverlordExportRunDataMap.
    public virtual IList<float> RawY { get; set; }
}


// Must be in different namespace from DlsAppOverlordExportRunData!!!
public class DlsAppOverlordExportRunDataMap : IAutoMappingOverride<DlsAppOverlordExportRunData>
{
    public void Override(AutoMapping<DlsAppOverlordExportRunData> mapping)
    {
        // Creates table called "RawY", with primary key
        // "DlsAppOverlordExportRunData_Id", and numeric column "Value"
        mapping.HasMany(x => x.RawY)
               .Element("Value");
    }
}

I would expect the same approach to work with ILists of strings.

Karren answered 22/12, 2009 at 22:4 Comment(2)
Ok this looks interesting. Is this something that can be defined via conventions? It seems FNH is focussing on conventions to customise automapping.Remunerative
I don't think so. I got the solution by asking the question on the Fluent mailing list, and believe it was one of the FNH authors who gave it to me. If it could be done by a single convention, I think he would have suggested that.Karren
K
4

Since I posted my first answer, the Fluent NHibernate team have fixed this problem.

You can now automap ILists of C# value types (strings, ints, floats, etc).

Just make sure you have a recent version of FNH.

Karren answered 4/10, 2010 at 23:12 Comment(2)
Alas, this is almost a year late for my needs - regardless its good to see FNH implemented this, it was the only real hurdle I encountered when using it for a large LOB app.Remunerative
Kudos Tom for coming back a year later to provide this update.Catchfly
K
1

Think of it this way...how would you do it without hibernate? Well, You'd probably have a table with a foreign-key and string column? Now, how do you do that with Hibernate? You setup another class with a many-to-one and string property. Then you map a collection of that class.

Klemperer answered 21/12, 2009 at 22:39 Comment(2)
Ok, point taken. I just dont like having to create all these totally trivial classes to wrap primitive collections. Can I have the automapping infer this for me?Remunerative
Oh, so you don't need to create another class? I think that's possible...nhforge.org/doc/nh/en/index.html#collections-ofvalues see how they gave an example of a set of ints, looks like you do a regular collection then define an element property for your string.Klemperer

© 2022 - 2024 — McMap. All rights reserved.