本文介绍了NHibernate中的继承和延迟加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
请参阅以下课程:
public class Employee
{
public Employee Manager {get;组; }
}
public class ShopFloorEmployee:Employee {...}
$ b $ public class OfficeEmployee:Employee {...}
公共类部门
{
公共职员经理{get;组; }
}
这里是NHibernate映射文件:
<?xml version =1.0encoding =utf-8?>
namespace =Domain.Entities
assembly =Domain>
< class name =Employee>
< id name =Idcolumn =Idtype =long>
< generator class =identity/>
< / id>
< discriminator column =Typetype =string/>
< subclass name =ShopFloorEmployeediscriminator-value =ShopFloorEmployeeextends =Employee/>
< / subclass>
< subclass name =OfficeEmployeediscriminator-value =OfficeEmployeeextends =Employee/>
< / subclass>
< / class>
< / hibernate-mapping>
<?xml version =1.0encoding =utf-8?>
namespace =Domain.Entities
assembly =Domain>
< class name =Department>
< id name =Idcolumn =Idtype =long>
< generator class =identity/>
< / id>
< discriminator column =Typetype =string/>
< / class>
< / hibernate-mapping>
这些代理似乎会导致我的问题。例如,如果我加载一个部门,那个部门的经理(我们称他为Bob,他是一个ShopFloorEmployee)将是EmployeeProxy类型。然后,在同一个会话中,如果我专门加载所有ShopFloorEmployees的列表,它们将全部属于ShopFloorEmployee类型,除了Bob,其将是EmployeeProxy类型。然后,我根本无法将Bob作为ShopFloorEmployee,因为它遵循了不同的继承路径。
代理服务器通常需要通过它们递归加载雇员来避免经理每次加载一个部门或员工。
我在这里做了一些根本性的错误,或者这是NHibernate的怪癖吗?如果这是一个怪癖,那么是否有解决方法?我已经考虑在加载部门之后明确地关闭会话,但这似乎太过分了。 解决方案
这个问题的常见解决方法是添加 Self
属性以访问非代理类型:
公共虚拟员工Self
{
get {return this; }
}
然后您可以检查 Bob.Self是ShopFloorEmployee
。
个人而言,我非常谨慎地使用继承,我会在这里使用角色属性而不是子类。
Take the following classes:
public class Employee
{
public Employee Manager { get; set; }
}
public class ShopFloorEmployee : Employee { ... }
public class OfficeEmployee : Employee { ... }
public class Department
{
public Employee Manager { get; set; }
}
and here are the NHibernate mapping files:
<?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>
These proxies seem to be causing me problems. For instance, if I load a Department, the Manager of that department (let's call him Bob, who is a ShopFloorEmployee) will be of type EmployeeProxy. Then, in the same session, if I specifically load a list of all ShopFloorEmployees, they will all be of type ShopFloorEmployee except Bob, who will be of type EmployeeProxy. I then can't cast Bob as a ShopFloorEmployee at all, because it has followed a different inheritance path.
The proxies are necassary to avoid recursively loading loads of Employees via their manager each time I load either a Department or Employee.
Am I doing something fundamentally wrong here, or is this a quirk of NHibernate? If it is a quirk then is there a work around? I have considered explicitly closing the session after loading the department but this seems just too hacky.
解决方案
A common workaround for this issue is to add a Self
property to access the non-proxied type:
public virtual Employee Self
{
get { return this; }
}
Then you can check Bob.Self is ShopFloorEmployee
.
Personally I use inheritance very sparingly and I would use a "role" property here instead of subclassing.
这篇关于NHibernate中的继承和延迟加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!