参加以下课程:
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>
这些代理似乎给我带来了麻烦。例如,如果我加载一个部门,该部门的经理(让我们称他为Bob,他是ShopFloorEmployee)将是EmployeeProxy类型。然后,在同一个会话中,如果我专门加载所有ShopFloorEmployees的列表,它们都将是ShopFloorEmployee类型,除了Bob,它将是EmployeeProxy类型。然后,我根本无法将Bob转换为ShopFloorEmployee,因为它遵循不同的继承路径。
代理是必要的,以避免每次加载部门或员工时通过其经理递归加载员工负载。
我在这里做了一些根本错误的事情,还是这是NHibernate的怪癖?如果这是一个怪癖,那么有一个解决方法吗?我已经考虑过在加载部门后明确关闭会话,但这看起来太糟糕了。
答案 0 :(得分:3)
此问题的常见解决方法是添加Self
属性以访问非代理类型:
public virtual Employee Self
{
get { return this; }
}
然后您可以查看Bob.Self is ShopFloorEmployee
。
我个人非常谨慎地使用继承,我会在这里使用“角色”属性而不是子类化。
答案 1 :(得分:2)
这是一个常见的NHibernate pitfall。尝试将Manager
引用更改为No proxy association。
答案 2 :(得分:1)
我有一个类似的问题,请看这里: fluent nhibernate polymorphism. how to check for type of class
我选择使用基于访客模式的解决方案
您不需要关闭延迟加载也不需要使用有趣的属性来返回自我对象