April 12, 2007

HNibernate: Many-to-Many Joins

OK, this one has waisted a few too many hours for me and another developer here in the office. Resolving many-to-many table relationships in NHibernate.

Note: last time I blogged on NHibernate I was told things were easier with ActiveRecord. But I'm still not using ActiveRecord.

I will set things up first. Here is our table layout and relationships:

If you can't see the image, there are three tables: TableA, TableB, and TableC. TableA and TableB both have relationships to TableC. A classic Many-To-Many table structure.

Now the first thing you have to decide is which table leads. Or which table is the master. That table will take care of actually adding and removing items from TableC. I will use TableA.

So in TableA's hbm you will have an entry that looks like this:
<bag name="TableBs" table="TableC">
<key column="TableA_id">
<many-to-many class="MyNamespace.TableB, MyNamespace" column="TableC_ID">
</many-to-many></key></bag>
and in the TableA class (this is C# kids), you should have this:
private IList<tableb> _tableBs = new List<tableb>();
public virtual IList<tableb> TableBs
{
get { return _tableBs ; }
set{ _tableBs = value; }
}
Ok, TableA is now setup as the master. Now to make TableB the slave.
In the TableB hbm.xml you will now see this
<bag name="TableAs" table="TableC" inverse="true">
<key column="TableB_ID">
<many-to-many class="MyNamespace.TableA, Aim.Domain" column="TableA_ID">
</many-to-many>
</key></bag>
Then the TableB class
protected IList<TableA> _tableAs = new List<TableA>();
public virtual IList<TableA> Contacts { get { return _tableAs ; } set { _tableAs = value; } }
It would be easy to miss the difference between the two, so here is the difference. In the TableB hbm there is a "inverse="true"". That is the only real difference, but it is a critical change to make if you want to be able to modify what items are related to what.

No comments: