NHibernate:实体的查询条件,可能是同一查询中的子类

时间:2010-02-17 01:17:06

标签: nhibernate entity subclass icriteria

这是我的2个实体的设置:

public class Person {
  public Guid Id {get;set;}
  public string Name {get;set;}
}

public class Immortal : Person {
  public string DarkName {get;set;}
}

以下是他们的映射:

<class name="Person">
  <id name="Id">
    <generator class="guid.comb"/>
  </id>
  <property name="Name" />

  <joined-subclass name="Immortal">
    <key column='PersonId' />
    <property name="DarkName" />
  </joined-subclass>
</class>

这就是设置,2个实体,一个是另一个的连接子类。我有一个搜索框架,它从表单中获取任意数量的条件,然后将适当的条件应用于查询,然后返回结果。

现在说我在这种情况下有一个单独的表格字段,“姓名” - 我想通过查看他们的姓名是否与姓名属性相匹配,将所有人带回来,无论是正常人还是特殊类别的神仙。人,但是对于一个不朽的人,如果他们的DarkName与形式中给出的匹配,我也想把它算作一个匹配。

所以这是我的困境,我该怎么做?我能用NHibernate的ICriteria做的最好的事情是在Immortal上创建一个子查询来检查那里的名字,然后查看根Person ID是否在该子查询中。然而,当使用成千上万人的表时,这种获得结果的方法非常低效,甚至可以在我的真实世界情况下超时请求(30s +)。

我也愿意在HQL中这样做,因为我想我想在Immortal上使用外连接来检查这个字段,但是我不能让HQL在任意属性上的2个不同实体上进行连接 - 连接据我所知,必须基于映射中的直接关联。例如,这就是我喜欢的内容:

select person from Person person
  outer join Immortal immortal on immortal.PersonId = person.Id
  where
    person.Name = :name or
    immortal.DarkName = :name

你说stackoverflow怎么说?

1 个答案:

答案 0 :(得分:3)

以下条件查询几乎可以生成您想要的SQL。

它利用了条件查询引擎中的一些松懈。

var list = session.CreateCriteria<Person>()
    .Add( Expression.Disjunction()
        .Add( Expression.Eq( "Name", name ) )
        .Add( Expression.Eq( "ImmortalName", name ) )
        )
    .List<Person>();

生成以下SQL:

SELECT this_.Id             as Id0_0_,
       this_.Name           as Name0_0_,
       this_1_.ImmortalName as Immortal2_1_0_,
       case 
         when this_1_.Id is not null then 1
         when this_.Id is not null then 0
       end as clazz_0_
FROM   person this_
       left outer join immortal this_1_
         on this_.Id = this_1_.Id
WHERE  (this_.Name = 'foo' /* @p0 */
         or this_1_.ImmortalName = 'foo' /* @p1 */)

我使用了以下类映射:

<class name="Person" table="person">
    <id name="Id">
        <generator class="identity" />
    </id>
    <property name="Name" />
    <joined-subclass name="Immortal" table="immortal">
        <key column="Id" />
        <property name="ImmortalName" />
    </joined-subclass>
</class>