Mapping IDictionary (Key/Value)

1,666 views
Skip to first unread message

Peter

unread,
Mar 25, 2009, 7:31:00 AM3/25/09
to Fluent NHibernate
I had read any discussion regarding dictionary mapping with Fluent
NHibernate, either standard or automatic mapping, within this group.
But till now it is not clear to me if this is supported like it is in
NHibernate or it is not supported with Fluent NHibernate. I am using
the trunk version of Fluent NHibernate Revision 430.

When I try to automap:

public IDictionary<string, QuoteProperty> Properties { get; set; }


I get the following exception:
System.Reflection.TargetInvocationException: Exception has been thrown
by the target of an invocation
The type or method has 2 generic parameter(s), but 1 generic argument
(s) were provided. A generic argument must be provided for each
generic parameter..

when I try to do it the standard mapping way:

HasMany<QuoteProperty>(x => x.Properties);

I get the following exception:
System.ApplicationException : Error while trying to build the Mapping
Document for ...
----> NHibernate.MappingException : Could not compile the mapping
document: (XmlDocument)
----> NHibernate.MappingException : Error mapping generic
collection
Domain.Persistent.Quote.Properties: expected 1 generic parameters, but
the property type has 2

If I just use a IList everything is fine for both mapping types.
public IList<QuoteProperty> Properties { get; set; }

Can you please let me know if it is not supported, or do I need some
special/different setup ?

Thanks in adavnce,
Peter



James Gregory

unread,
Mar 25, 2009, 7:40:06 AM3/25/09
to fluent-n...@googlegroups.com
You need to specify it as a map, with an index of whatever the string represents.

HasMany(x => x.Properties)
  .AsMap(x => x.Name);

Where Name is whatever the string key is.

Paul Batum

unread,
Mar 25, 2009, 7:45:33 AM3/25/09
to fluent-n...@googlegroups.com
Depending on your situation, the overload for AsMap that takes a lambda might not be what you are after. I recently added a different overload for AsMap that allows you to specify the index and element settings without the lambda, so this might be the one to use if the map is not indexed by a property of QuoteProperty.

Peter

unread,
Mar 25, 2009, 9:08:47 AM3/25/09
to Fluent NHibernate
Thank you both very much for the fast answers,

but I still do not get it, sorry.

Should I map it like:
HasMany(x => x.Properties).AsMap(string, QuoteProperty); <= Invalid
expression term string

because the key of the dictionary is just a string which do not have a
property defined so far.

Can you please, let me know, how I can map it in this special case?

James Gregory

unread,
Mar 25, 2009, 9:24:52 AM3/25/09
to fluent-n...@googlegroups.com
So to clarify, your QuoteProperty class doesn't have a property that maps to the value of your key in the dictionary?

Peter

unread,
Mar 25, 2009, 9:39:05 AM3/25/09
to Fluent NHibernate
Yes, you are right, I do not have a property for the key.
I use the key internal of my Quote class to administrate the
dictionary, which is perfect fine for the domain.
Any hints how I should change it to make it persistent ?

Martin Nilsson

unread,
Mar 25, 2009, 9:46:03 AM3/25/09
to fluent-n...@googlegroups.com
Is it possible to map dictionaries now? Then this is fixed or?

http://code.google.com/p/fluent-nhibernate/issues/detail?id=94

Peter

unread,
Mar 25, 2009, 9:57:58 AM3/25/09
to Fluent NHibernate
I want to do something like:

public IDictionary<string, QuoteProperty> Properties { get; set; }

<map name="Properties" cascade="all">
<key column="PropertyId"/>
<index column="Name" type="String"/>
<one-to-many
class="QuoteProperty"/>
</map >

Any hints are welcome, how to map this.

Peter

unread,
Mar 25, 2009, 11:09:04 AM3/25/09
to Fluent NHibernate
I have tried the following after searching the sources, ....

HasMany(x => x.Properties).AsMap<string>(index => index.WithColumn
("Id").WithType<string>(),
element => element.WithColumn
("Value").WithType<QuoteProperty>());

But I have received the following exception:

Data.Tests.Quote_Mapping_Tests (TestFixtureSetUp):
NHibernate.MappingException : Could not determine type for:
Domain.Persistent.QuoteProperty, Domain, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null, for columns:
NHibernate.Mapping.Column(Value)

Please let me know what I do wrong.

James Gregory

unread,
Mar 25, 2009, 11:46:23 AM3/25/09
to fluent-n...@googlegroups.com
Peter: I've just committed a change that should hopefully work for you. If you get the latest source, then try this:

HasMany(x => x.Properties)
  .AsMap("Name")
  .KeyColumnNames.Add("PropertyId");

Peter

unread,
Mar 25, 2009, 1:26:21 PM3/25/09
to Fluent NHibernate
Hi James thank you very much:-)

it works for my case for standard mapping. I tested automatic mapping
too, but I guess automatic mapping is currently not supported.
But your change works for standard mapping !

If you are interested, the resulted hbm file is:
<class name="Quote" table="`Quote`" xmlns="urn:nhibernate-
mapping-2.2">
<id name="Id" type="Int64" column="Id">
<generator class="identity" />
</id>
<property name="Date_Time" type="DateTime">
<column name="Date_Time" />
</property>
<map name="Properties">
<key column="PropertyId" />
<index type="System.String, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089" column="Name" />
<one-to-many class="Domain.Persistent.QuoteProperty, Domain,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</map>
</class>

James Gregory

unread,
Mar 25, 2009, 2:18:08 PM3/25/09
to fluent-n...@googlegroups.com
That sounds right, I didn't make any changes to automapping. You could use the ForTypesThatDeriveFrom call, as that will have the changes in.

// on your AutoPersistenceModel
ForTypesThatDeriveFrom<MyEntity>(m =>
  m.HasMany(x => x.Properties)
       .AsMap("Name"));
Reply all
Reply to author
Forward
0 new messages