Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate bidirectional many-to-many association

Tags:

nhibernate

I have a class with following description:

public class Customer {
    public ISet<Client> Contacts { get; protected set;}
}

I want to map Contacts property onto following table:

CREATE TABLE user_contacts (
    user1 uuid NOT NULL,
    user2 uuid NOT NULL
)

I want it to map bidirectionally, i.e. when Customer1 added to Customer2's Contacts, Customer1's Contacts collection should contain Customer2 (maybe only after entity reload). How could I do that?

Update Sure I can map left-to-right and right-to-left sets and then combine then at runtime, but it'll... hmm... untasty... Is there other solution? Any way, thank you very match, FryHard!

like image 332
Artem Tikhomirov Avatar asked Nov 05 '22 23:11

Artem Tikhomirov


1 Answers

Take a look at this link on what hibernate calls unidirectional many-to-many associations. In Castle ActiveRecord I make use of HasAndBelongsToMany links, but I am not sure how exactly it is mapped in nhibernate.

Though taking a look at your question a little deeper, it looks like you will be linking bidirectionally from customer to user_contacts, which could break the many-many link. I will play with an example and see what I can come up with.

An Export of the hbm files from ActiveRecord shows this

<?xml version="1.0" encoding="utf-16"?>
<hibernate-mapping  auto-import="true" default-lazy="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:nhibernate-mapping-2.2">
  <class name="NHibernateMapping.Customer, NHibernateMapping" table="Customer" schema="dbo">
    <id name="Id" access="property" column="Id" type="Int32" unsaved-value="0">
      <generator class="identity">
      </generator>
    </id>
    <property name="LastName" access="property" type="String">
      <column name="LastName" not-null="true"/>
    </property>
    <bag name="ChildContacts" access="property" table="user_contacts" lazy="false">
      <key column="user1" />
      <many-to-many class="NHibernateMapping.Customer, NHibernateMapping" column="user2"/>
    </bag>
    <bag name="ParentContacts" access="property" table="user_contacts" lazy="false" inverse="true">
      <key column="user2" />
      <many-to-many class="NHibernateMapping.Customer, NHibernateMapping" column="user1"/>
    </bag>
  </class>
</hibernate-mapping>

ActiveRecord example:

[ActiveRecord("Customer", Schema = "dbo")]
public class Customer
{
    [PrimaryKey(PrimaryKeyType.Identity, "Id", ColumnType = "Int32")]
    public virtual int Id { get; set; }

    [Property("LastName", ColumnType = "String", NotNull = true)]
    public virtual string LastName { get; set; }

    [HasAndBelongsToMany(typeof(Customer), Table = "user_contacts", ColumnKey = "user1", ColumnRef = "user2")]
    public IList<Customer> ChildContacts { get; set; }

    [HasAndBelongsToMany(typeof(Customer), Table = "user_contacts", ColumnKey = "user2", ColumnRef = "user1", Inverse = true)]
    public IList<Customer> ParentContacts { get; set; }
}

Hope it helps!

like image 99
FryHard Avatar answered Nov 15 '22 08:11

FryHard