NHibernate陷阱:many-to-one关联中的ghost对象

问题

NHibernate的many-to-one关联是支持多态的(理应),然而一不留神,代码就掉进了陷阱。考虑这个类图,OrderLine 有一个Product属性,同时,Product有两个子类。

image

这个关联的映射:
 
<many-to-one Name="Product" class="Product" column="ProductId" />
 

接下来,要为 Food 的订单行执行一点特别的业务逻辑:

OrderLine line = ...;
if (line.Product is Food)
{
  // 永远不会执行到这里
}
 

即使 line 的 Product 是 Food,这个判断也不会成立,针对Food的业务逻辑永远不会执行。

原因

造成这个问题的原因是 NHibernate 默认使用代理对象实现 many-to-one 的延迟加载,程序运行后,类结构实际上是这样的(紫色的类是nhibernate生成的代理类,实际的代理类名称与图中不同):

image

line对象构造出来以后,他的 Product 属性没有初始化,实际上,它是 ProductProxy 的实例(ghost对象),而 ProductProxy 和 Food 并无转换关系,表达式 (line.Product is Food) 永远为 false。

解决

为了避免 ghost 对象的问题,需要对关联的延迟加载稍稍做一点配置。如果不需要延迟加载,可以禁用:

<many-to-one Name="Product" class="Product" column="ProductId" lazy="false"/>

或者,如果仍然需要延迟加载,可以使用 no-proxy 选项,告诉 NHibernate 仍然延迟加载Product关联,但是不要使用代理对象。

<many-to-one Name="Product" class="Product" column="ProductId" lazy="no-proxy" />
posted @ 2011-08-17 07:07  梦幻泡影  阅读(462)  评论(1编辑  收藏  举报