Mapping a dictionary
HI,
Given the following tables
TableA
---------
Id
TableB
-------
Id
TableAB
------------
AId
BId
EnumValue
And the given classes
public class A {
public virtual int Id { get; private set; }
public virtual IDictionary<EnumValues, B> Dictionary { get; private set; }
}
public class B { public virtual int Id { get; private set; } }
How would I map this fluently?
Thanks
Andy
Support Staff 2 Posted by Paul Batum on 30 Jun, 2010 11:12 AM
Hi Andy,
I actually have an example of something pretty close to this in my fluent
nhibernate test project. If you need to download a working example, you can
get it here:
http://github.com/paulbatum/Fluent-NH-Test-Bed/tree/fluent-dictionary-entity-bool
<http://github.com/paulbatum/Fluent-NH-Test-Bed/tree/fluent-dictionary-entity-bool>But
the gist of it is that this mapping:
HasManyToMany(x => x.Groups)
.AsMap(null)
.AsTernaryAssociation()
.Element("IsManager", ep => ep.Type<bool>());
Gives me this joining table:
create table Groups (
User_id INTEGER not null,
IsManager INTEGER,
Group_id INTEGER not null,
primary key (User_id, Group_id)
)
I think that is pretty close to what you want, right?
Sorry that the fluent interface for maps is so damn confusing.. we
definitely plan on doing something about this.
3 Posted by Andy on 30 Jun, 2010 12:31 PM
Paul,
Thanks so much! I would have never guessed to pass null into AsMap. I am just missing one thing, which confuses me a bit.
In case, the ep.Type statement has MyType as an enum. I have a convention which should map enums as int values, but I get an exception that the type MyType is not mapped.
I am going to try just creating an IUserType for the enum and I think that should correct it, but I wanted to see if there was something else I'm missing?
Thanks again for your help!
Andy
Support Staff 4 Posted by Paul Batum on 30 Jun, 2010 01:54 PM
Passing null doesn't make sense in all cases of using maps, but it works in
this one. It sucks :/
There should be an easy way to handle the enum, I can't remember it right
now though. I'll see if I can dig something up.
5 Posted by Andy on 30 Jun, 2010 02:01 PM
Paul,
I'm getting an exception for the mapping: NHibernate.MappingException : An association from the table MyManyToManyTable refers to an unmapped class: DomainModel.MyType.
Any ideas?
6 Posted by Andy on 30 Jun, 2010 02:31 PM
Paul,
Just wanted to update again; even if I use int for the Dictionary's key, I get the same exception: NHibernate.MappingException : An association from the table MyManyToManyTable refers to an unmapped class: System.Int32.
I need to add to that we are using a branch we've been updating from April 30th. That branch had another fix we needed, and we were able to also fix the Convention / Subclass map problem we are working on in another thread. We were not able to fix the convention problem in a later branch because how Fluent handles the conventions internally changed pretty dramtically the next day.
It's possible the dictionary mapping will work for you if its going against the latest code, but not for us because we're only a version around .363.
Since I'm sure you have limited time, it might be better to focus on the that issue so that we can get current.
Thanks for all your help so far.
Andy
7 Posted by Andy on 01 Jul, 2010 05:26 PM
Ok, so I sort of have things figured out. I'm left with two possiblities here. Either the Fluent .AsMap() call I can't get quite right, or there's a bug. I'm leaning toward the former, since the AsMap call is fairly complex.
The Hbm that was generated via your recommend call was outputting this Xml:
By trial and error, I found the Xml I wanted is actually this:
This has everything I want (except no primary key is set).
Any ideas?
Support Staff 8 Posted by Paul Batum on 05 Jul, 2010 12:42 PM
Sorry Andy, I think I lead you astray with my previous mapping - I got it
mixed up on which side of the dictionary the entity was.
Lets try again:
<http://github.com/paulbatum/Fluent-NH-Test-Bed/tree/fluent-dictionary-enum-entity>
HasManyToMany<Book>(x => x.FavouriteBooks)
.Table("FavouriteBooks")
.ParentKeyColumn("CustomerID")
.ChildKeyColumn("BookID")
.AsMap<string>("BookType");
It makes this xml:
<map cascade="all" name="FavouriteBooks" table="FavouriteBooks"
mutable="true">
<key>
<column name="CustomerID" />
</key>
<index type="System.String, mscorlib, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="BookType" />
</index>
<many-to-many class="Domain.Book, Domain, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null">
<column name="BookID" />
</many-to-many>
</map>
and this table:
create table FavouriteBooks (
CustomerID INTEGER not null,
BookID INTEGER not null,
BookType TEXT not null,
primary key (CustomerID, BookType)
)
You can download the whole working thing here:
http://github.com/paulbatum/Fluent-NH-Test-Bed/tree/fluent-dictionary-enum-entity
Let me know how it goes.
<http://github.com/paulbatum/Fluent-NH-Test-Bed/tree/fluent-dictionary-enum-entity>
On Fri, Jul 2, 2010 at 3:30 AM, Andy <
***@tenderapp.com<tender%***@tenderapp.com>
> wrote:
9 Posted by Andy on 06 Jul, 2010 02:02 PM
Paul,
Thanks for the new suggestion, however that leads me back to the An association from the table FavoriteBooks refers to an unmapped class: System.Collections.Generic.KeyValuePair`2[[BookTypeEnum],[Book]]
Andy
Support Staff 10 Posted by Paul Batum on 07 Jul, 2010 11:39 AM
Have you looked at the sample I linked to? How is my sample different to
your scenario?
Support Staff 11 Posted by Paul Batum on 07 Jul, 2010 11:40 AM
Oh I think I misunderstood, that error message looks like it came from my
sample.
But it works for me!
What did you do exactly? Did you grab my sample but run it using non-current
FNH binaries?
12 Posted by Andy on 07 Jul, 2010 03:51 PM
Hi Paul,
Sorry for the confusion, I changed the types to match your sample, but the error came from my application using the same mapping. However, that was the message I was getting when the map contained the element tag within the map tag instead of the many-to-many tag.
We are not using the latest version though; we're using a version committed the day after the .363 release. The .363 release had a bug where Components were not working with Subclass map, but the fix was in the next commit. However that next commit also introduced the bug where Conventions are not being applied in Subclass maps. We grabbed the source and fix that bug as well, because the next commit after that (on 6/1/2010 I believe) totally reworked how conventions are done internally in Fluent, and we were not able to figure out how to fix the Convention + Subclass map issue.
So we've been stuck on a release from Apr 30, and it's possbile the AsMap works fine in a more recent release... but without the Convention and SubclassMap working as it was in RTM, we can't move off of our forked version...
Thats why I was hoping you could continue looking into this issue: https://fluentnhibernate.tenderapp.com/discussions/help/164-convent...
The sooner we can go back to using the most recent Fluent, the better.
Andy
Support Staff 13 Posted by James Gregory on 03 Aug, 2010 11:30 PM
As a user of our Dictionary support, you might be interested in our rework of this feature: Dictionary mapping redesign. We're working on simplifying the syntax, while making it more flexible at the same time.
Support Staff 14 Posted by Paul Batum on 05 Aug, 2010 01:48 PM
Unfortunately Andy won't be able to try the new syntax without running into
the aforementioned issues with latest code base, specifically around the
application of conventions to components (this is the problem that I tried
to fix but the fix wasn't right and we had to roll it back)
On Wed, Aug 4, 2010 at 9:32 AM, James Gregory <
***@tenderapp.com<tender%***@tenderapp.com>
> wrote:
15 Posted by Andy Johnstone on 05 Aug, 2010 01:59 PM
Sorry I didn't reply to James, but yes, Paul is correct. We've been unable to upgrade without a way to use conventions within components.
-----Original Message-----
From: Paul Batum [mailto:tender+d1fb761e6aa64b44dcbdcdc4947d093bd14368a4a=***@sendgrid.me] On Behalf Of Paul Batum
Sent: Thursday, August 05, 2010 9:51 AM
To: ***@mywebgrocer.com
Subject: Re: Mapping a dictionary [Help and guidance]