views:

26

answers:

2

I am trying to relate 2 items. I have a table that is simply an Id field, and then 2 columns for the Item Id's to relate. I want it to be a 2 way relationship - that is, if the items appear twice in the table, I only want one relationship connection back.

So, here's my item:

public class Item
{
   public virtual Guid ItemId {get; set;}

   public virtual string Name {get; set;}

   public virtual IList<Item> RelatedItems {get; set;}
}

The table for relating the items looks like this:

CREATE TABLE RelatedItems
(
   RelatedItemId   uniqueidentifier   DEFAULT(NEWID()) NOT NULL,
   ItemId          uniqueidentifier   NOT NULL,
   RelatedId       uniqueidentifier   NOT NULL,

   CONSTRAINT PK_RelatedItems PRIMARY KEY CLUSTERED (RelatedItemId)
)

What is the best way to map this connection?

+1  A: 

You need to use a "HasMany" mapping. I think the following may work:

public class Item : ClassMap<Item>
{
  Id(x=>x.Id)
    .Column("ItemId");

  Map(x=>x.Name);

  HasMany(x=>x.RelatedItems)
    .KeyColumn("RelatedId")
    .Table("RelatedItems")
    .LazyLoad()
    .AsList();    
}

You can always use a convention for the Id field. And consider cascade delete options on the HasMany collection.

Aim Kai
The problem is that the relationship only works one way with that. I need it to work both directions.
Josh
A: 

I had to do it the hard way (read HACK).

HasManyToMany(x => x.RelatedTo)
                .Table("RelatedItems")
                .ParentKeyColumn("ItemId")
                .ChildKeyColumn("RelatedItemId");

HasManyToMany(x => x.RelatedToMe)
                .Table("RelatedItems")
                .ChildKeyColumn("ItemId")
                .ParentKeyColumn("RelatedItemId");

Then in my class I have a read only collection called RelatedItems which joins the two lists and selects distinct items to return.

Josh