Creating one-to-many relationship in NHibernate

We have recently brought in NHibernate in our environment and I was the first one in the team to do something real with it. It was going perfect until this one-to-many relationship and then I had to consult the architect in UK to get it going 😦 Infact I successfully implemented many-to-many but could not do one-to-many . *&#%&*#W(*(*&%#

Anyways, we had a class SearchCritera having a list of SearchCriterion. The mapping file looked like:

<class name="BusinessObjects.Search.SearchDocumentCriteria" table="searchdocumentcriteria">
<id name="Id" column="id">
<generator class="sequence">
<param name="sequence">pc_searchdocumentcriteria</param>
</generator>
</id>
<bag name="Criteria" lazy="false" cascade="all" inverse="true">
<key column="criteriaid"/>
<one-to-many class="BusinessObjects.Search.SearchDocumentCriterion"/>
</bag>
</class>
<class name="BusinessObjects.Search.SearchDocumentCriterion" table="searchdocumentcriterion">
<id name="Id" column="id">
<generator class="sequence">
<param name="sequence">pc_searchdocumentcriterion</param>
</generator>
</id>
<property name="FieldName" column="fieldname" type="string"/>
<many-to-one name="Id" class="BusinessObjects.Search.SearchDocumentCriteria" column="criteriaid" not-null="true"/>
<bag name="Expression" lazy="false" cascade="all" inverse="true">
<key column="criterionid"/>
<one-to-many class="Search.SearchDocumentCriterionOperatorValue"/>
</bag>
</class>

Look at the red line, it maps back to the parent class’s column Id. This is what I found in the manual and an example on the internet as well. But we were getting the error:

Unknown entity class: System.Int32

Later we found that we need to have a parent reference in the child class as well which make the relationship 2-way. So we added the following property in the SearchDocumentCriterion class:

public virtual SearchDocumentCriteria Parent { get; set; }

And the following change in the mapping file:

<many-to-one name="Parent" class="BusinessObjects.Search.SearchDocumentCriteria" column="criteriaid" not-null="true"/>

Note the Parent property instead of Id property. This solved the problem 😀 Anyone having a better solution for one-to-many relationship in NHibernate? Yes, I don’t like the two-way relationship.

 

 

Share this post : digg it! Facebook it! live it! reddit! technorati! yahoo!

Advertisements

9 thoughts on “Creating one-to-many relationship in NHibernate

  1. You’ve made a correct bidirectional one-to-many mapping. If you need only unidirectional mapping – if you don’t need to navigate to SearchDocumentCriteria class from SearchDocumentCriterion, you can set the inverse attribute in the Criteria bag to false and delete one-to-many association from SearchDocumentCriterion.

    Btw, we’re using NConstruct (http://www.nconstruct.com for generating NHibernate mapping files and classes and it serves us for the learning process for NHibernate as well.

  2. Thanks for the informative post. I will check it out too but I think that I did try to do that as well. Anyways, nconstruct looks appealing.

  3. Hello,

    I would like to take to this opportunity to ask a question about one-to-many. I ahve two classes:

    GeneralInformation and famousPlacesInLondon

    public class GeneralInformation
    {

    private int id;

    public virtual int Id
    {
    get { return id; }
    set { id = value; }
    }

    private IList famousPlacesOutLondon;

    public virtual IList FamousPlacesOutLondon
    {
    get { return famousPlacesOutLondon; }
    set { famousPlacesOutLondon = value; }
    }
    }

    public class FamousPlacesInLondon
    {
    private int id;

    public virtual int Id
    {
    get { return id; }
    set { id = value; }
    }
    private string link;

    public virtual string Link
    {
    get { return link; }
    set { link = value; }
    }
    private string title;

    public virtual string Title
    {
    get { return title; }
    set { title = value; }
    }

    }
    }

    My mapping are as follows:

    If I fill the GeneralInformation with data and do a save using NHibernate, everything gets inserted into the appropriate table, except the ForeignKey GeneralInformationId. What is wrong?

    TIA
    Yaz

  4. You cannot see my mapping because it did not let me because of the angle brackets. I have solved it. I had forgotten to flush after the save. I however got another question.

    public class A
    {

    private IList cl;
    public ILIST CL
    {
    get{return cl;}
    set (cl=value;}
    }

    // Other members
    }

    public class B
    {

    private IList cl;
    public ILIST CL
    {
    get{return cl;}
    set (cl=value;}
    }

    // other members
    }

    public class C
    {

    private string name;
    public string Name
    {
    get{return name;}
    set (name=value;}
    }

    // Other members
    }

    in the ILIST it expects a class of type C.

    What would be the mapping in NHibernate?

    TIA
    Yaz

  5. I see that there is a one-to-many relationship between A & C and B & C. You should use a BAG inside your class A and B mappings. It would go something like this:

    class name=”A” table = ….
    your id column mapping

    bag name=”name of list”
    key column=”id column in C”
    one-to-many class=”C”
    bag
    class

    class name=”C” table ….
    your id column mapping

    many-to-one class=”A” property=”reference to A” column=”id of A” not-null=”true”
    class

    Note that you need to have a reference to A inside C.

  6. Thanks for the answer, in my object model Class C does not have a reference to A, I do not need it. The problem that I am having is that it looks like I have a many to many relationship, but in fact I do not have one. In NHibernate is there something like a reference. I my model, the way I see it is that A has a reference to a collection class of type C and B has a reference to a collection of type C.

    Cheers
    Yaz

  7. Hi Yazid, I believe nhibernate needs that reference for its internal use. Thats not wrong, let it do this thing the best possible way. However that will not make it a many-to-many relationship because bag is at one side only. If you find another solution please let us know.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s