尝试访问 NHibernate 中的类型鉴别器字段
Posted
技术标签:
【中文标题】尝试访问 NHibernate 中的类型鉴别器字段【英文标题】:Trying to access a field of type discriminator in NHibernate 【发布时间】:2012-03-02 06:09:22 【问题描述】:我的地图上有一个类库,它继承了两个新类
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Business" namespace="Business.Test">
<class name="BaseExample" table="base_example" abstract="true" discriminator-value="0">
<id name="Id" column="id" type="Int64" unsaved-value="0">
<generator class="native"/>
</id>
<discriminator column="domain" type="Int16" not-null="true" force="true" />
....
....
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Business" namespace="Business.Test">
<subclass name="Example1" extends="BaseExample" discriminator-value="1">
....
....
</subclass>
</hibernate-mapping>
一切正常,但如果我要求该字段,例如:
var Clients = ClientFactory.GetAll().Where(c => c.UserData.BaseExample.Domain == 1);
抛出此异常:异常消息:无法解析属性:Domain of: Business.Entities.BaseExample
如何判断它是属于一类还是另一类?
【问题讨论】:
【参考方案1】:鉴别器用于 NHibernate 的幕后(参见 Rippo 的示例)。这个想法是您查询 类 并将该类映射中的适当鉴别器注入到查询中。
但是,如果出于某种原因您需要在属性中提供该信息,则可以将其作为属性包含在内。这意味着
<class name="BaseExample" table="base_example" abstract="true" discriminator-value="0">
<id name="Id" column="id" type="Int64" unsaved-value="0">
<generator class="native"/>
</id>
<discriminator column="domain" type="Int16" not-null="true" force="true" />
<property name="domain" column="domain" type="Int16" update="false" insert="false" />
....
....
</class>
将属性声明为只读 (update="false" insert="false"
) 很重要,因为这是一个完全由 nhibernate 管理的列。
【讨论】:
在你的课上我也会包括:-public int Domain get; protected set;
如果您希望它在应用程序代码中可见,这将很有用,但如果您只希望它用于查询,则不需要它
你需要一个完全映射属性的setter吗?
我的意思是,您可以通过在属性定义中添加属性 access="noop" 来避免映射类中的属性。这样,在查询期间不会获取属性值,但您可以在查询时使用它,例如使用 HQL。【参考方案2】:
使用QueryOver
获取base_example
表中BaseExample
类的所有记录,您可以这样做:-
session.QueryOver<BaseExample>().List();
要获取所有 Example1
记录,您会这样做
session.QueryOver<Example1>().List();
获取所有Example2
记录:-
session.QueryOver<Example2>().List();
换句话说,NHibernate 足够聪明,可以自动为您在查询中添加 where 子句 Domain=1
或 Domain=2
。
还应注意,如果您想要基表中的所有记录并有一个循环,那么您可以这样做:-
var list = session.QueryOver<BaseExample>().List();
foreach(var item in list)
if (item is Example1)
Output(Example1) //Do something with Example1
if (item is Example2)
Output(Example2) //Do something with Example2
【讨论】:
以上是关于尝试访问 NHibernate 中的类型鉴别器字段的主要内容,如果未能解决你的问题,请参考以下文章
使用 Fluent NHibernate 将每个层次结构映射到现有数据库的表,没有鉴别器列