Fluent NHibernate Object Referencing Instance of Itself / Self Referencing, Error “Repeated column in mapping for collection”

I came across a problem with a Schema Fluent Nhibernate was generating for me yesterday.  I was getting the error message Repeated column in mapping for collection”.

I had an object, let’s call it “Item” which referenced instances of the same type, let’s call them “AssociatedItems”.
Thinking of a simple real-life example, when you do an oil change on your car you should change the oil filter and the sump-plug washer too.  So an oil filter Item would have associated items of oil and sump-plug washer.  Sump-plug washer would have associated items of oil and oil filter etc.

So the object looked something like this :

public class Item
{
    public virtual int Id {get; set;}
    public virtual string Code {get; set;}
    public virtual string Description {get; set;}
    public virtual string IList<Item> AssociatedItems {get; set;}
}

Looks pretty straighforward.  Now to the Mapping :

Public ItemMap()
{   
    Id(x => x.Id);
    Map(x => x.Code);
    Map(x => x.Description);
    HasManyToMany(x => x.AssociatedItems);
}

OK, really simple.

Generating the schema, a table to handle the many-to-many relationships between Items and AssociatedItems is created.  It’s called something wierd like AssociatedItemsToAssociatedItems though and it only has one field / column called “Item_Id”.  I’m also getting an error message “repeated column in mapping for collection – Item_Id” – What’s going on?     The database generation seems to be getting confused because of the self reference / relationship and is trying to create a table with field name “Item_Id” for the parent object and “Item_Id” for the child object.

Getting around the problem was quite straightforward though and only involved a change to the mapping class.
If you provide NHibernate with specific PK / FK names for the relationships it will generate a table with two fields of the specificed names, a composite key for the relationships.   Great!

HasManyToMany(x => x.AssociatedItems)
     .ParentKeyColumn("Item_Id")   
     .ChildKeyColumn("AssociatedItem_Id")

It still gives you a table with a crappy name though – bollocks!   What you need to do now though is tell NHibernate what it should call the table holding the relationship, explicitly define the name of the relationship table :

    .Table("AssociatedItemToItem");

So, the new, working map definition is :

Public ItemMap()
{
   Id(x => x.Id);
   Map(x => x.Code);
   Map(x => x.Description);
   HasManyToMany(x => x.AssociatedItems)
        .ParentKeyColumn("Item_Id")
        .ChildKeyColumn("AssociatedItem_Id")
        .Table("AssociatedItemToItem");
}
Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s