Наследование и ленивая загрузка в 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