2

我必须映射两个具有外键关系的简单表。其中一个表是Contact包含列id(int 类型的主键)、nameaddressguid(新添加且不是主键)。另一个是phone__number包含列id(int 类型的主键)、 contact ___ 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>
    {
    }
}

当我分别加载联系人和电话号码时,它可以工作,但是在添加 set 元素以获得一对多关系后,nhibernate 给出了一个错误:

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

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

4

3 回答 3

11

只要记住这个

  • Bag是使用IList实现的
  • Set 是使用 ISet 实现的
  • List 使用 ArrayList 或 List 实现
  • Map 使用 HashedTable 或 IDictionary 实现

如果您想使用 IList,请使用第一条规则,即更改您的 hbm.xml 以使用 Bag 而不是 Set,您的 Phonenumbers 类也应该继承自 IList 而不是 List,如果您想使用 List,您需要更改映射文件以使用 List集。

于 2009-03-29T10:18:36.283 回答
3

我认为您的 PhoneNumbers 类需要继承自Iesi.Collections.ISet. 我不认为.NET 中默认提供了“Set”类型。请参阅休眠常见问题解答

<set> 映射到 Iesi.Collections.ISet。该接口是与 NHibernate 一起分发的 Iesi.Collections 程序集的一部分。

于 2009-03-14T07:37:38.420 回答
1

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

如果您将您的收藏定义为

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

然后我认为它会起作用。

为了更好地控制对您的收藏的访问,您可以像这样修改您的联系人类:

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>
于 2009-03-14T07:51:16.547 回答