尝试访问 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=1Domain=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 将每个层次结构映射到现有数据库的表,没有鉴别器列

鉴别器

我可以使用 Entity Framework 4 CTP5 访问 TPH 映射中的鉴别器值吗

第二部分 Nhibernate中的类型

discriminator 鉴别器

如何使用 mongoosejs 用鉴别器覆盖父模式字段