简体   繁体   English

NHibernate一对多映射问题

[英]NHibernate one-to-many mapping problem

I have to map two simple table with a foreign key relationship. 我必须映射两个具有外键关系的简单表。 One of the tables is Contact containing columns id (primary key of type int), name , address and guid (newly added and is not the primary key). 其中一个表是包含列id (类型为int的主键), 名称地址guid (新添加且不是主键)的Contact The other one is phone__number containing columns id (primary key of type int), contact___id (foreign key of id in contact table) and phone__number . 另一种是含phone__numberID(int类型的主键),contact___id(在接触表ID的外键)和phone__number。

The mapping file for Contact table is as below : 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>

The mapping file for Phone_number table is : 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>

The Contact and PhoneNumber classes are : 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>
    {
    }
}

When I load the contact and phone_numbers separately it works, but after adding the set element to get a one-to-many relationship nhibernate is giving an error : 当我分别加载contact和phone_numbers时,它可以工作,但是在添加set元素以获得一对多关系后,nhibernate会给出一个错误:

NHibernate.MappingException: Invalid mapping information specified for type OfflineDbSyncWithNHibernate.Models.Contact, check your mapping file for property type mismatches NHibernate.MappingException:为类型OfflineDbSyncWithNHibernate.Models.Contact指定的无效映射信息,检查映射文件中是否存在属性类型不匹配

I am new to nHibernate so I am not sure if there is a mistake in the set element or I should not even be using it. 我是nHibernate的新手,所以我不确定set元素中是否有错误,或者我甚至不应该使用它。 Any help will be appreciated. 任何帮助将不胜感激。

Just remeber this 记住这一点

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

If you want to use IList use first rule ie change your hbm.xml to use Bag instead of Set also your Phonenumbers class should inherit from IList not List, if you want to use List you will need to change your mapping file to use List instead of Set. 如果你想使用IList使用第一个规则,即改变你的hbm.xml来使用Bag而不是Set你的Phonenumbers类应该继承IList而不是List,如果你想使用List你将需要更改你的映射文件来使用List而不是集合。

I think your PhoneNumbers class needs to inherit from a subtype of Iesi.Collections.ISet . 我认为你的PhoneNumbers类需要继承Iesi.Collections.ISet的子类型。 I don't think there is a "Set" type provided in .NET by default. 我不认为默认情况下.NET中提供了“Set”类型。 See hibernate FAQ 请参阅hibernate FAQ

The <set> maps to an Iesi.Collections.ISet. <set>映射到Iesi.Collections.ISet。 That interface is part of the Iesi.Collections assembly distributed with NHibernate. 该接口是与NHibernate一起分发的Iesi.Collections程序集的一部分。

Your collection-type should be an interface, because NHibernate will provide it's own type that implements that interface when an object is retrieved from the DB. 您的集合类型应该是一个接口,因为NHibernate将提供它自己的类型,当从数据库中检索对象时,该类型实现该接口。

If you define your collection as 如果您将集合定义为

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

Then I think it will work. 然后我认为它会起作用。

In order to better control the access to your collection, you can modify your Contact class like this: 为了更好地控制对集合的访问,您可以像这样修改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 )
    {
        ...
    }
}

Then, you have to make sure that in your mapping of the Contact class, you specify that NHibernate should access the field _phoneNumbers instead of the property PhoneNumber: 然后,您必须确保在您的Contact类的映射中,指定NHibernate应该访问字段_phoneNumbers而不是属性PhoneNumber:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM