在NHibernate中创建和检索关联的映射

时间:2011-01-12 05:36:11

标签: c# .net nhibernate associations mappings

假设我有两个持久性类CatHat。让我们假设两者之间的关系是双向一对多的,因为在Cat中可以有许多不同的帽子,我们可以在两个方向上遍历映射。为了在每个类的实例之间创建关联,我应该能够并且如果我错了就纠正我,请执行以下操作:

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);

考虑到这一点,我是否应该通过执行以下操作来检索与redHat相关联的Cat?

Hat hat = hatService.FindById(1); // redHat has Id 1
Cat cat = hat.Cat; // cat should be whiskers

不幸的是,当我尝试使用这种技术时,cat会在最后一行中作为空对象生成。我猜我在Cat.hbm.xml中的一对多映射中遗漏了一些东西,或者至少我希望它很简单。以下是目前的情况:

<set name="Hats" inverse="true">
  <key column="Id"/>
  <one-to-many class="Hat"/>
</set>

我在Hat.hbm.xml中没有映射,因为添加一个导致了“重复映射”错误。我在关联映射上阅读了Hibernate documentation,但仍然无法使其正常工作。我做错了什么?

下面填写完整的地图文件:

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>

修改

我认为问题在于我没有初始化Cat类中的ISet<Hat>值。但是,我遇到了一个新问题。当我尝试访问关联时,我收到此错误:

Could not initialize proxy - no Session.

我认为如果我在DAO中创建一个方法可以很容易地避免这种情况,我可以将它包装在这样的会话中:

public Cat GetRelatedCat(Hat hat)
{
    Cat cat;
    using (ISession session = HibernateUtil.GetSessionFactory().OpenSession())
    {
        cat = hat.Cat;
    }
    return cat;
}

这会产生相同的“无会话”错误。我很难过。

2 个答案:

答案 0 :(得分:0)

  1. 您需要在hat.hbm中添加多对一条目。 我认为应该有效。

  2. 然后你必须设置关联的两面

    whiskers.Hats.Add(REDHAT);

    redHat.Cat =晶须;

  3. 我认为这样可以使你的样本有效。

    您的“无会话”问题的原因是,集合代理仅适用于创建它的会话。因此,在您的示例中,它仅适用于创建Hat实例的会话。可以将代理与另一个会话连接,但通常不会推荐,因为它对事务边界和数据一致性有复杂的影响。

答案 1 :(得分:0)

我通过创建一个SessionManager解决了这个问题,它允许我打开一个Session,执行任何事务并访问Session singleton中的任何集合代理,然后关闭Session。