Say I have two persistent classes Cat
and Hat
. Let's imagine that the relationship between the two is bidirectionally one-to-many, as in a Cat can have many different Hats, and we can traverse the mapping in both directions. In order to create an association between an instance of each class, I should be able to, and correct me if I'm wrong, do the following:
Cat whiskers = new Cat();
Hat redHat = new Hat();
redHat.Id = 1; // normally assigned by generator but this makes example more explicit
whiskers.Hats.Add(redHat);
catService.Save(whiskers);
hatService.Save(redHat);
With that in mind, should I not be able to retrieve the Cat which is associated with redHat by doing the following?
Hat hat = hatService.FindById(1); // redHat has Id 1
Cat cat = hat.Cat; // cat should be whiskers
Unfortunately, when I try to use this technique, cat results as a null object in that last line. I'm guessing I am missing something in my one-to-many mapping in Cat.hbm.xml, or at least I hope it's something that simple. Here's what it currently looks like:
<set name="Hats" inverse="true">
<key column="Id"/>
<one-to-many class="Hat"/>
</set>
I have no mapping in Hat.hbm.xml since adding one resulted in a "duplicate mapping" error. I read the Hibernate documentation on association mappings, but still can't get this working. What am I doing wrong?
Complete mapping files below:
Cat.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Domain"
namespace="Domain">
<class name="Cat" table="cats" lazy="true">
<id name="Id">
<generator class="increment" />
</id>
<property name="Name" />
<set name="Hats" inverse="true">
<key column="Id"/>
<one-to-many class="Hat"/>
</set>
</class>
</hibernate-mapping>
Hat.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Domain"
namespace="Domain">
<class name="Hat" table="hats" lazy="true">
<id name="Id">
<generator class="increment" />
</id>
</class>
</hibernate-mapping>
Edit
I believe the problem was that I was not initializing the ISet<Hat>
value in the Cat class. However, I've run into a new problem. When I try to access the associations, I get this error:
Could not initialize proxy - no Session.
I figured this would be easily avoided if I created a method in my DAO where I could wrap it in a session like this:
public Cat GetRelatedCat(Hat hat)
{
Cat cat;
using (ISession session = HibernateUtil.GetSessionFactory().OpenSession())
{
cat = hat.Cat;
}
return cat;
}
This yields the same "no session" error. I'm stumped.
I solved the problem by creating a SessionManager which allows me to open a Session, perform any transactions and access any collection proxies within the Session singleton, and then close the Session.