I have a Table of Companies, and I'm trying to build a matrix of competitors between them.
For example: McDonalds is a Competitor of Wendy's, and vice-versa.
Here's the mappings I've tried:
HasManyToMany(x => x.Competitors)
.ParentKeyColumn("IssuerID")
.ChildKeyColumn("CompetitorID")
.Table("Competitors")
.Cascade.All().Not.LazyLoad();
as well as:
Table("Issuer");
Id(x => x.Key).Column("Id").GeneratedBy.Assigned();
Map(x => x.Name).Length(1000);
HasManyToMany(x => x.Competitors).ParentKeyColumn("IssuerID").ChildKeyColumn("CompetitorID").Table("Competitors").Cascade.All().Not.LazyLoad();
When I add a competitor to an Issuer, I can see the correct mapping in the database.
So If I do:
McDonalds.AddCompetitor(Wendys);
I will see the correct data in the DB. I will also see the correct DB in the Entities when i get McDonalds using NHibernate.
But, if I return Wendy's from Nhibernate and look at the Competitors object:
Wendys.Competitors
I don't see McDonalds. I can understand why because Wendy's was added to McDonalds as a Child.
How can I modify this so I can view the competitors from both directions?
I came up with the following solution in my local tests. Actually I am not really satisfied as I would hope for a better support. Maybe there is. If someone finds it please post.
Having a store like this (shrinked down to the relevant parts of competitors):
public class Store
{
public virtual int Id { get; protected set; }
public virtual IList<Store> Competitors { get; set; }
}
I used the following mapping (same as you):
HasManyToMany(x => x.Competitors)
.ParentKeyColumn("Store_Id")
.ChildKeyColumn("Competitor_Id")
.Table("CompetitorsMapping");
As you state it does not work with this. But from the examples provided in the Git Repo of fluentnhibernate it wraps the add of the lists anyway.
The "FirstProject" example does something similar by adding an employee to a store. It first sets the store on the employee and then adds the employee to the Staff of the store (okay a bit different then). But it automatically takes care of dependencies.
So you could solve your problem by not setting directly but by wrapping the add and remove (From your sample code it looks like you already do that):
public class Store
{
public virtual void AddCompetitor(Store competitor)
{
if (!Competitors.Any(x => x.Id == competitor.Id))
{
competitor.Competitors.Add(this);
Competitors.Add(competitor);
}
}
public virtual void RemoveCompetitor(Store competitor)
{
competitor.Competitors.Remove(this);
Competitors.Remove(competitor);
}
}
What I especially don't like is the contains check on Competitors. Don't know how it performs and behaves. But without you can add the same competitor over and over. Making the list long.
I am new to fluentnhibernate. Maybe some setting could prevent the double adds automatically. I'd be interested in that setting.