NHibernate Single Table Inheritance - PullRequest
       8

NHibernate Single Table Inheritance

1 голос
/ 20 марта 2009

У меня проблемы с настройкой структуры на основе ролей с использованием наследования и NHibernate.

По сути, я хотел бы иметь абстрактный класс с именем ObjectInRole. Этот класс (и соответствующая таблица базы данных) содержит RoleId, ObjectId и ObjectType (это будет столбец дискриминатора). Столбец дискриминатора будет типом объекта, который получает роль.

Для простоты предположим, что существует объект User, который содержит список (мешок) ролей. Мне бы хотелось, чтобы у меня был класс UserInRole, который был бы подклассом ObjectInRole.

Я создал эту сумку так:

<bag name="Roles" table="ObjectInRole" where="ObjectType = 'AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core'" generic="true"
     access="field.pascalcase-underscore" lazy="true">
  <key column="ObjectId" />
  <many-to-many class="AthletesCafe.Core.Domain.System.Roles.Role, AthletesCafe.Core" column="RoleId" />
</bag>

Я настроил отображение для ObjectInRole так:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="AthletesCafe.Core.Domain.System.Roles" assembly="AthletesCafe.Core">
  <class name="ObjectInRole" table="ObjectInRole" lazy="true" abstract="true">
<id name="ID" type="Int32" unsaved-value="0">
  <column name="ID" not-null="true" unique="true" index="PK_ObjectInRole"/>
  <generator class="identity" />
</id>
<discriminator column="ObjectType" type="String" insert="true" force="true"/>
<property name="ApplicationName" column="ApplicationName" type="String" not-null="false" length="255" />
<property name="ObjectId" column="ObjectId" type="int" not-null="true" />
<property name="ObjectType" column="ObjectType" type="String" />

<many-to-one name="Role" column="RoleId" class="AthletesCafe.Core.Domain.System.Roles.Role, AthletesCafe.Core" not-null="true" cascade="none" />

<subclass name="AthletesCafe.Core.Domain.System.Roles.UserInRole" 
          discriminator-value="AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core">
  <many-to-one name="User" column="ObjectId" class="AthletesCafe.Core.Domain.System.Users.User, AthletesCafe.Core" not-null="false" cascade="none" />
</subclass>

Имея эту настройку и запустив ее, я не могу получить поле ObjectType для сохранения при добавлении новой роли в коллекцию для объекта User. Он сохраняет новую запись в таблице ObjectToRole, но ObjectType имеет значение null. Глядя на сумку, она не загрузится в коллекцию. Я думаю, что я сузил это до структуры подкласса, которая настраивается неправильно или что сумка настроена неправильно. Я склоняюсь к пакету, так как думаю, что он может рассматривать коллекцию как группу абстрактного класса вместо подкласса UserInRole.

Пожалуйста, выскажите свои мысли по любой области. Спасибо!

EDIT:

Таким образом, вместо того, чтобы пытаться добавить в пакет (User.Roles.add (Role)) и иметь много-многих сохраняющих связывающий объект, я решил, что просто добавлю объект в таблицу. Я получаю новую ошибку:

null id in AthletesCafe.Core.Domain.System.Roles.UserInRole entry (don't flush the Session after an exception occurs) 

Если посмотреть на класс выше, я установил объект User и объект Role. Идентификатор является полем идентификации и указывается как таковой. Я в полной растерянности.

1 Ответ

2 голосов
/ 21 марта 2009

OK! После долгой игры с файлами сопоставления я обнаружил недокументированную проблему (по крайней мере, я не нашел упоминания об ошибке, которую я совершал).

При использовании подкласса родительский класс не может содержать сопоставление для свойства, которое является столбцом дискриминатора. Если вы посмотрите на второй документ сопоставления, который я опубликовал, он показывает суперкласс и подкласс. Дискриминатор суперкласса - это столбец ObjectType. Я также сопоставляю это как свойство с абстрактным классом ObjectInRole. Ты не сможешь это сделать. После удаления этой строки все работало правильно (без сохранения пакета).

Сумка, кажется, является проблемой, которая не поддается контролю с помощью всего, что я нашел в документации. Я не могу найти другой экземпляр, где абстрактный класс сохраняется через сопоставление. Похоже, что NHibernate не знает, что класс связывания является объектом UserInRole, а не объектом ObjectInRole. Изучая все варианты, которые предоставляются для узла bag, не было очевидного способа сообщить NHibernate, через какой класс он связывается, чтобы установить связь «многие ко многим». Из того, что я могу сказать, это не волнует, но более или менее рассматривает таблицу как таблицу, а не как отображенный объект. Если бы можно было сказать, что это добавить что-то для вставки, возможно, это было бы возможно, но я не видел никакой информации по этому поводу.

...