Вопрос

Мне нужно сопоставить две простые таблицы с отношением внешнего ключа.Одна из таблиц такова Контакты содержащий столбцы ID (первичный ключ типа int),Имя, адрес и guid (недавно добавлен и не является первичным ключом).Другой - это телефон__номер содержащий столбцы ID (первичный ключ типа int), контактный___id (внешний ключ идентификатора в таблице контактов) и телефон__номер.

Файл сопоставления для таблицы контактов выглядит следующим образом :

<?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.Модели.Свяжитесь с нами, проверьте ваш файл сопоставления на наличие несоответствий типов свойств

Я новичок в NHibernate, поэтому я не уверен, есть ли ошибка в элементе set или я даже не должен его использовать.Любая помощь будет оценена по достоинству.

Это было полезно?

Решение

Просто запомни это

  • Bag реализован с помощью IList
  • Set реализован с помощью ISet
  • Список реализуется с помощью ArrayList или списка
  • Карта реализована с помощью HashedTable или IDictionary

Если вы хотите использовать IList, используйте первое правило, т.е. измените свой hbm.xml чтобы использовать Bag вместо Set, также ваш класс Phonenumbers должен наследоваться от IList, а не List, если вы хотите использовать List, вам нужно будет изменить свой файл сопоставления, чтобы использовать List вместо Set.

Другие советы

Я думаю, что ваш класс PhoneNumbers должен наследоваться от подтипа Iesi.Collections.ISet. Я не думаю, что есть & Quot; Set & Quot; тип предоставляется в .NET по умолчанию. См. часто задаваемые вопросы

  

< set > карты на   Iesi.Collections.ISet. Этот интерфейс   является частью Iesi.Collections   сборка распространяется с помощью NHibernate.

Тип вашей коллекции должен быть интерфейсом, потому что 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>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top