[英]Nhibernate: Pull back most derived type in "Table-per-class hierarchy"
我正在解决有关 NHibernate 配置中“每类层次结构表”设置中的几个<subclass>
元素的问题。 当我点击数据库时,我正在尝试获取父 class 的“最衍生类型”。 即,当我获取EnergySource
object 时,我希望基础类型为Grid
或Primary
,具体取决于<discriminator...>
。
如果我将属性lazy="false"
添加到EnergySource
class 配置中,一切实际上都按预期工作。 例如,我可以成功地将EnergySource as Grid
进行投射,我可以在EnergySource
上使用反射,如果它与鉴别器匹配,我可以运行GetType()
并中继:
UnderlyingSystemType: { Name = "Grid" ...
但是通过延迟加载,我得到了一个失败的演员表(只有null
)&:
UnderlyingSystemType: { Name = "EnergySourceProxy" ...
这里发生了什么? 根本问题是由延迟加载引起的吗?
我的配置是这样设置的(这是一个旧应用程序):
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Domain.EnergySource, Domain" table="library_EnergySource" lazy="true">
<cache usage="read-write" />
<id name="Id" column="EnergySourceID" unsaved-value="0">
<generator class="identity" />
</id>
<discriminator formula="case when EnergySourceTypeID in (1,2,3) then 1 else 4 end" />
<property name="Name" />
<many-to-one name="Type" column="EnergySourceTypeID" not-null="true" insert="false" update="false" />
<subclass name="Domain.Grid, Domain"
extends="Domain.EnergySource, Domain"
discriminator-value="1">
</subclass>
<subclass name="Domain.PrimaryEnergy, Domain"
extends="Domain.EnergySource, Domain"
discriminator-value="4">
</subclass>
</class>
</hibernate-mapping>
课程只是:
namespace Domain
{
public class Grid : EnergySource { }
public class Primary : EnergySource { }
public class EnergySource
{
public virtual string Name { get; set; }
public virtual EnergySourceType Type { get; set; }
}
public class EnergySourceType
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
}
本质上,是的,问题在于 class 是“延迟加载的”。 当我尝试从另一个 object 访问EnergySource
时,它是一个属性(例如item.EnergySource
),我得到了 NHibernate 的“代理”,它可以促进延迟加载,如下所示:
简而言之...... [我们正在使用的] 是一个延迟加载的 object、NHibernate,目前还不知道它是什么。 但是因为它必须返回一些东西,所以它返回一个 [我们的对象] 的代理,它会在需要时加载实际的实例。 [但是] 当你想降低价值时,这会导致一些问题。
有关更多详细信息,请参阅“问题”链接。 但从本质上讲,一旦我们有一个代理 object,我们就不能将它转换为它所代理的类型的子类,不幸的是......这里有一些解决方法,取自以下链接:
lazy="false"
禁用延迟加载lazy="no-proxy"
(在我的情况下,这不起作用,但这可能是由于旧版本的 Z111BBE34492093E9894EF9E8B3E01ADZ 或我对文档的理解有误; 这当然是它的设计目的):<many-to-one name="EnergySource" lazy="no-proxy"/>
return Session.GetSessionImplementation()
.PersistenceContext.Unproxy(EnergySource) as Grid;
this
,其工作原理是“泄漏对实际对象的引用”。 这类似于上述选项,但不需要任何特定于 NH 的工作:public virtual object Actual { get { return this; } }
...
return item.EnergySource.Actual as Grid //Works
他们还提供了通用方法的代码,以进一步简化此过程。 还有一些注意事项,可能也适用于Unproxy
方法。
public virtual T As<T>() where T : Entity
{
return this as T;
}
...
Animal animalProxy = catLover.Pet;
Cat cat = animalProxy.As<Cat>();
// Cat will be the actual object of type Cat
// Or null if animalProxy isn't one
这是 NHibernate 管理的底层 object 的后门。 它应该只用于访问派生类的属性。 对行为使用多态性。 您永远不应将检索到的 object 传递给 NHibernate 方法,例如更新或删除。
资料来源:
this
解决方法: http://sessionfactory.blogspot.com/2010/08/hacking-lazy-loaded-inheritance.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.