Hash

Creating one-to-many relationship in NHibernate

March 31, 2009 · 9 Comments

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 :D 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!

Categories: .NET · CodeProject
Tagged: , , , , , , ,

9 responses so far ↓

  • Usman Ahmed // November 12, 2008 at 11:39 pm

    good.

  • Tone // November 17, 2008 at 3:54 am

    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.

  • hashfactor // November 18, 2008 at 12:20 am

    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.

  • Yazid // April 23, 2009 at 9:24 pm

    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

  • hashfactor // April 24, 2009 at 2:30 am

    Hi, can’t see your mappings.

  • Yazid // April 27, 2009 at 6:53 am

    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

  • hashfactor // April 27, 2009 at 11:53 am

    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.

  • Yazid // April 27, 2009 at 6:27 pm

    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

  • hashfactor // April 30, 2009 at 11:02 am

    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 Comment