NHibernate一对多映射问题

时间:2009-03-14 07:28:07

标签: c# .net nhibernate nhibernate-mapping one-to-many

我必须使用外键关系映射两个简单表。其中一个表格是联系,其中包含 id 列(类型为int的主键),名称地址和< strong> guid (新添加并且不是主键)。另一个是 phone__number ,其中包含列 id (类型为int的主键),联系___ id (联系人表中id的外键)和 phone__number

Contact表的映射文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="OfflineDbSyncWithNHibernate" default-lazy="true" namespace="OfflineDbSyncWithNHibernate.Models">
  <class name="Contact" table="Contact">
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>

    <property name="Name" column="name" type="string"/>
    <property name="Address" column="address" type="string"/>
    <property name="Guid" column="guid" type="string"/>

    <set lazy="true" batch-size="6" table="phone_number" name="PhoneNumbers" fetch="join" inverse="false" cascade="all" >
      <key foreign-key="FK_contact_phone_number" column="contact_id"/>
      <one-to-many class="PhoneNumber" />
    </set>

  </class>
</hibernate-mapping>

Phone_number表的映射文件是:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="OfflineDbSyncWithNHibernate" default-lazy="true" namespace="OfflineDbSyncWithNHibernate.Models">
  <class name="PhoneNumber" table="phone_number">
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>
    <property name="ContactId" column="contact_id" />
    <property name="Number" column="phone_number" />
  </class>
</hibernate-mapping>

Contact和PhoneNumber类是:

namespace OfflineDbSyncWithNHibernate.Models
{
    public class Contact
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual string Address { get; set; }
        public virtual string Guid { get; set; }
        public virtual PhoneNumbers PhoneNumbers { get; set; }
    }
}

namespace OfflineDbSyncWithNHibernate.Models
{
    public class PhoneNumber
    {
        public virtual int Id { get; set; }
        public virtual int ContactId { get; set; }
        public virtual string Number { get; set; }
    }
}

namespace OfflineDbSyncWithNHibernate.Models
{
    public class PhoneNumbers : List<PhoneNumber>
    {
    }
}

当我分别加载contact和phone_numbers时,它可以工作,但是在添加set元素以获得一对多关系后,nhibernate会出错:

NHibernate.MappingException:为类型OfflineDbSyncWithNHibernate.Models.Contact指定的映射信息无效,请检查映射文件中是否存在属性类型不匹配

我是nHibernate的新手所以我不确定set元素中是否有错误,或者我甚至不应该使用它。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:11)

请记住这个

  • Bag使用IList
  • 实现
  • Set使用ISet
  • 实现
  • 使用ArrayList或List
  • 实现列表
  • 使用HashedTable或IDictionary
  • 实现地图

如果你想使用IList使用第一个规则,即改变你的hbm.xml使用Bag而不是Set你的Phonenumbers类应该继承IList而不是List,如果你想使用List,你需要将你的映射文件更改为使用List而不是Set。

答案 1 :(得分:3)

我认为您的PhoneNumbers类需要从Iesi.Collections.ISet的子类型继承。我不认为默认情况下.NET中提供了“Set”类型。请参阅休眠FAQ

  

&lt; set&gt;映射到   Iesi.Collections.ISet。那个界面   是Iesi.Collections的一部分   与NHibernate一起发布的程序集。

答案 2 :(得分:1)

您的集合类型应该是一个接口,因为当从数据库中检索对象时,NHibernate将提供它自己的类型来实现该接口。

如果您将收藏定义为

public virtual ISet<PhoneNumber> Phonenumbers = new HashedSet<Phonenumber>();

然后我认为它会起作用。

为了更好地控制对集合的访问,您可以像这样修改Contact类:

public class Contact
{
    public virtual int Id {get;set;}
    ..

    private ISet<Phonenumber> _phoneNumbers = new HashedSet<PhoneNumber>();

    public ReadOnlyCollection<Phonenumber> PhoneNumbers
    {
        get 
        {
           return new List<Phonenumber>(_phoneNumbers).AsReadOnly();
        }
    }

    public void AddPhonenumber( Phonenumber n )  
    {
        n.Contact = this;
        _phoneNumbers.Add(n);
    }

    public void RemovePhoneNumber( PhoneNumber n )
    {
        ...
    }
}

然后,你必须确保在你的Contact类的映射中,指定NHibernate应该访问字段_phoneNumbers而不是属性PhoneNumber:

<set name="PhoneNumbers" access="field.camelcase-underscore" ... >
   ...
</set>