views:

1067

answers:

1

Hi,

My class has a field of type Dictionary<string, List<string>>. What's the best way to map it with NHibernate? I'd better leave it as a field, don't want to expose it.

Thanks a lot!

ulu

+2  A: 

You can't directly map it. There are two rules to consider:

  • Always use interfaces for collections (eg. IList<T>, IDictionary<K,V>)
  • NH does not support nested collections. I've never seen an application for it before and never heard someone requesting it.

Put your list of string into a class and use interfaces:

class StringList
{
  IList<string> Strings { get; private set; }
}

class Entity
{
  private IDictionary<string, StringList> stringDict;
}

You might even see some advantages of having such a class.

Mapping:

<class name="Entity">
  ...
  <map name="stringDict" table="Entity_StringDict" access="field">
    <key column="Entity_FK"/>
    <index column="Key" type="System.String"/>
    <composite-element class="StringList">
      <bag name="Strings" table="Entity_StringDict_Strings">
        <key column="Entity_StringDict_FK"/>
        <element type="System.String" column="String"/>
      <bag>
    <composite-element>
  <map>
</class>

Maps to three Tables:

  • Table Entity
  • Table Entity_StringDict
    • Column Entity_FK
    • Column Key
  • Table Entity_StringDict_Strings
    • Column Entity_StringDict_FK
    • Column String
Stefan Steinegger
Fantastic, I'll give it a try!
ulu
Hmm I'm getting an error: XML validation error: The element 'composite-element' in namespace 'urn:nhibernate-mapping-2.2' has invalid child element 'bag' in namespace 'urn:nhibernate-mapping-2.2'. List of possible elements expected: 'parent, property, many-to-one, nested-composite-element' in namespace 'urn:nhibernate-mapping-2.2'.Using Nhibernate 2.0.1..
ulu
Also, the docs say, "Composite elements may contain components but not collections".
ulu
I ended up adding an entity instead of a value class (StringList in your example), and my design became better I believe. Can we call it Mapping Driven Development?Anyway, thanks for your help, you pointed me to the right direction.
ulu
In NH 2.1, you can put collections into composite-elements. Sometimes it's better to write some additional classes to design complex structures. "Mapping Driven Development" sound rather bad to me, because the class model shouldn't be driven by NH, even if there are some trade-offs. NH tries to influence your model as little as possible.
Stefan Steinegger
@Stefan Steinegger: Are you sure collections are allowed within `<map><composite-element>`? It does not seem to work on my NH 2.1 based project.
Jørn Schou-Rode
@Jørn: You're right, it doesn't work either for my project. I just had in mind that you don't need an entity class anymore in some situation. Have to investigate this.
Stefan Steinegger

related questions