【问题标题】:Trying to access a field of type discriminator in NHibernate尝试访问 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

如何判断它是属于一类还是另一类?

【问题讨论】:

    标签: .net nhibernate orm nhibernate-mapping


    【解决方案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
    } 
    

    【讨论】:

      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多