2

外部キー関係を持つ 2 つの単純なテーブルをマップする必要があります。テーブルの 1 つは、列id (int 型の主キー)、nameaddress、およびguid (新しく追加され、主キーではありません) を含むContactです。もう 1 つは、列id (int 型のプライマリ キー)、contact___ id (contact テーブルの id の外部キー)、およびphone__numberを含む 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 要素を追加して 1 対多の関係を取得した後、nhibernate でエラーが発生します:

NHibernate.MappingException: タイプ OfflineDbSyncWithNHibernate.Models.Contact に指定されたマッピング情報が無効です。プロパティ タイプの不一致についてマッピング ファイルを確認してください

私は nHibernate を初めて使用するので、set 要素に誤りがあるのか​​、それとも使用すべきではないのかわかりません。どんな助けでも大歓迎です。

4

3 に答える 3

11

これだけ覚えておいてください

  • Bag は IList を使用して実装されています
  • Set は ISet を使用して実装されます
  • List は ArrayList または List を使用して実装されます
  • マップは HashedTable または IDictionary を使用して実装されます

IList を使用する場合は、最初のルールを使用します。つまり、hbm.xml を Set の代わりに Bag を使用するように変更します。また、Phonenumbers クラスは List ではなく IList から継承する必要があります。List を使用する場合は、マッピング ファイルを変更して List を使用する必要があります。セットの。

于 2009-03-29T10:18:36.283 に答える
3

あなたの PhoneNumbers クラスは のサブタイプから継承する必要があると思いますIesi.Collections.ISet。.NET でデフォルトで提供される「Set」タイプはないと思います。休止状態のFAQを参照してください

<set> は Iesi.Collections.ISet にマップされます。このインターフェイスは、NHibernate で配布される Iesi.Collections アセンブリの一部です。

于 2009-03-14T07:37:38.420 に答える
1

オブジェクトがDBから取得されると、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 がプロパティ PhoneNumber ではなくフィールド _phoneNumbers にアクセスするように指定する必要があります。

<set name="PhoneNumbers" access="field.camelcase-underscore" ... >
   ...
</set>
于 2009-03-14T07:51:16.547 に答える