Наследование и ленивая загрузка в NHibernate

Пройдите следующие занятия:

public class Employee 
{ 
    public Employee Manager { get; set; }
}

public class ShopFloorEmployee : Employee { ... }

public class OfficeEmployee : Employee { ... }

public class Department 
{
    public Employee Manager { get; set; }
}

и вот файлы сопоставления NHibernate:

  <?xml version="1.0" encoding="utf-8" ?>
  <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                     namespace="Domain.Entities" 
                     assembly="Domain">
    <class name="Employee">
      <id name="Id" column="Id" type="long">
        <generator class="identity"/>
      </id>
      <discriminator column="Type" type="string"/>
      <many-to-one name="Manager" class="Employee" column="ManagerId" lazy="proxy" />

      <subclass name="ShopFloorEmployee" discriminator-value="ShopFloorEmployee" extends="Employee"/>
      </subclass>

      <subclass name="OfficeEmployee" discriminator-value="OfficeEmployee" extends="Employee"/>
      </subclass>

    </class>
  </hibernate-mapping>

  <?xml version="1.0" encoding="utf-8" ?>
  <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                     namespace="Domain.Entities" 
                     assembly="Domain">
    <class name="Department">
      <id name="Id" column="Id" type="long">
        <generator class="identity"/>
      </id>
      <discriminator column="Type" type="string"/>
      <many-to-one name="Manager" class="Employee" column="ManagerId" lazy="proxy" />
    </class>
  </hibernate-mapping>

Эти прокси, кажется, вызывают у меня проблемы. Например, если я загружу отдел, менеджер этого отдела (назовем его Боб, который является ShopFloorEmployee) будет иметь тип EmployeeProxy. Затем, в том же сеансе, если я специально загрузлю список всех ShopFloorEmployee, все они будут иметь тип ShopFloorEmployee, кроме Боба, который будет иметь тип EmployeeProxy. Тогда я вообще не могу разыграть Боба как ShopFloorEmployee, потому что он пошел по другому пути наследования.

Прокси необходимы, чтобы избежать рекурсивной загрузки нагрузок сотрудников через их менеджера каждый раз, когда я загружаю либо отдел, либо сотрудника.

Я делаю что-то здесь в корне неправильно, или это причуды NHibernate? Если это странность, то есть ли обходной путь? Я рассмотрел явное закрытие сессии после загрузки отдела, но это кажется слишком хакерским.

3 ответа

Решение

Обычное решение этой проблемы - добавить Self свойство для доступа к непроксируемому типу:

public virtual Employee Self
{
   get { return this; }
}

Тогда вы можете проверить Bob.Self is ShopFloorEmployee,

Лично я использую наследование очень экономно, и я бы использовал здесь свойство "role" вместо подклассов.

Это распространенная ошибка NHibernate. Попробуйте изменить Manager ссылка на отсутствие прокси-ассоциации.

У меня был похожий вопрос, см. Здесь: беглый полиморфизм ниберната. как проверить тип класса

Я решил использовать решение на основе шаблона посетителя

Вам не нужно отключать ленивую загрузку или использовать забавные свойства для возврата объекта self

Другие вопросы по тегам