这是我的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怎么说?
答案 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>