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!


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.