1
votes

I have an NHibernate mapping issue which I could use help with - the documentation & samples seem very unclear to me.

I have one class which contains a dictionary of another classs. I'm unsure of the correct mapping and everything I've tried either fails to map, or gets a NHibernate exception on reading data.

The 2 classes are:

public class SnippetConfigParam
{
    public virtual int          SnippetValueKey { get; set; }
    public virtual string       ParamName { get; set; }
    public virtual string       Value{ get; set; }
}

public  class SnippetConfig
{
    public virtual int          SnippetKey { get; set; }


    public virtual ESnippetType Type{ get; set; }
    public virtual string       Name { get; set; }

    public virtual IDictionary<string, SnippetConfigParam> Params { get; set; }


    public virtual string       Description{ get; set; }


    public virtual VendorPage   Page{ get; set; }
}

My last mapping attempt was

<map name="Params"  table="SnippetConfigValue" lazy="false">
    <key column="SnippetConfigKey" />
    <index column="SnippetValueKey"  type="Int32"/>    
    <composite-element class ="SnippetConfigParam">
        <property name="ParamName"  />
        <property name="Value" />
    </composite-element>      
</map>

Which results in:

System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'.

So I'm clearly not understanding something. The database tables are:

Create Table SnippetConfig
    SnippetKey  int not null, 
    ...
    PrimaryKey( 'SnippetKey' )

  Create Table SnippetConfigValue
    SnippetValueKey  int  not null,
    ...
    PrimaryKey( 'SnippetValueKey' ),
    Key  'fk' ( 'SnippetConfigKey' ),
    Constraint 'fk' foreign key ('SnippetConfigKey' ) references 'SnippetConfig' ('SnippetKey' )...

Any advice would be greatly appreciated.

1

1 Answers

1
votes

Mapping dictionary in NHibernate could be a bit tricky. See the detail description here: Ayende's post about <map>. The key to understand it is in the mapping of the TKey and TValue (IDictionary<TKey, TValue>)

  • TKey is represented by <index> element
  • TValue could be element, composite-element, one-to-many

Because your TKey is string:

public virtual IDictionary<string, SnippetConfigParam> Params { get; set; }

The mapping representing it cannot be the int

<index column="SnippetValueKey"  type="Int32"/>

Change the Params proeprty to be IDictionary<int, SnippetConfigParam> and it should work.

NOTE: If you want the property SnippetValueKey of the class SnippetConfigParam to be filled extend the component

<composite-element class ="SnippetConfigParam">
    <property name="SnippetValueKey" formula="SnippetValueKey " 
              insert="false" update="false" />
    <property name="ParamName"  />
    <property name="Value" />
</composite-element>