Woutifier
Woutifier

Reputation: 313

Many-to-many relations in NHibernate using Mapping by Code

NHibernate has a system called Mapping by code that gives the developer the possibility to map their database in code (as the name says). I am using NHibernate 3.3.1.

I have done this for two classes: "Gebruiker" and "Lijst". They both have a list of eachother so this is a classic example of a many to many relation.

The mapping is as follows:

Gebruiker

        Set(l => l.Lijsten, map =>
            {
                map.Table("LijstGebruiker");
                map.Cascade(Cascade.All);
                map.Inverse(true);
                map.Key(k => k.Column("Gebruiker"));
            }, map => map.ManyToMany(p => p.Column("Lijst")));

Lijst

         Set(l => l.Gebruikers, map =>
             {
                 map.Table("LijstGebruiker");
                 map.Cascade(Cascade.All);
                 map.Key(k => k.Column("Lijst"));
             }, map => map.ManyToMany(p => p.Column("Gebruiker")));

As far as I know this should result in the table "LijstGebruiker" with the columns Gebruiker and Key.

Instead: NHibernate generates a table LijstGebruiker with three columns, one extra in the addition to the two expected ones: elt. Elt also refers to Lijst using a foreign key.

According to the websites I found on the internet about this this should not happen, yet it is. What am I doing wrong?

Upvotes: 1

Views: 2588

Answers (1)

SHSE
SHSE

Reputation: 2433

Apparently, this is some kind of strange behavior that happened when column name equals class name. The mapping generated by your code is:

Gebruiker

<set name="Lijsten" table="LijstGebruiker" inverse="true" cascade="all">
   <key column="Gebruiker" />
   <many-to-many class="Lijst" />
</set>

Lijst

<set name="Gebruikers" table="LijstGebruiker" cascade="all">
  <key column="Lijst" />
  <many-to-many class="Gebruiker" />
</set>

So, there is no column in many-to-many element. It could be a bug in NHibernate.

If you rename columns to Gebruiker_id and Lijst_id then everything works fine.

Another solution is to specify column name using multiple column definition method:

Gebruiker

Set(l => l.Lijsten, map =>
{
    map.Table("LijstGebruiker");
    map.Cascade(Cascade.All);
    map.Inverse(true);
    map.Key(k => k.Column("Gebruiker"));
}, map => map.ManyToMany(p =>
{
    p.Columns(x => x.Name("Lijst"));
}));

Lijst

Set(l => l.Gebruikers, map =>
{
    map.Table("LijstGebruiker");
    map.Cascade(Cascade.All);
    map.Key(k => k.Column("Lijst"));
}, map => map.ManyToMany(p =>
{
    p.Columns(x => x.Name("Gebruiker"));
}));

The mapping generated by the code is:

<set name="Lijsten" table="LijstGebruiker" inverse="true" cascade="all">
  <key column="Gebruiker" />
  <many-to-many class="Lijst">
    <column name="Lijst" />
  </many-to-many>
</set>

<set name="Gebruikers" table="LijstGebruiker" cascade="all">
  <key column="Lijst" />
  <many-to-many class="Gebruiker">
    <column name="Gebruiker" />
  </many-to-many>
</set>

Upvotes: 2

Related Questions