2010-02-17 61 views
3

这是我的2个实体设置:NHibernate的:在同一查询实体,可能一个子查询条件

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个实体,一个是另一个的连接子类。我有一个搜索框架,它从表单中获取任意数量的条件,然后将适当的条件应用于查询,然后返回结果。

现在说我在这种情况下有一个单一的表单字段,“名称” - 我想通过查看他们的名字是否与Name属性相匹配来恢复所有人,不管他们是普通人还是特殊类别的生命Immortals的人,但在Immortal的情况下,如果他们的DarkName与表单中给出的内容匹配,我还想将它计为匹配。

所以这是我的困境,我该怎么做?用NHibernate的ICriteria做的最好的事情是在Immortal上做一个子查询来检查那里的名字,然后看看根Person标识符是否在子查询中。但是,当处理数千人的表格时,这种获得结果的方法非常低效,甚至可以在我现实世界的情况下超时(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 

你说呢计算器?

+1

我们展示您的映射。 NHibernate支持多态查询,但是你有没有像这样映射它? – 2010-02-17 08:00:03

+0

好吧,我已经添加了它。 – 2010-02-17 19:01:44

回答

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> 
+0

过去几个小时,我一直在努力解决类似的问题。 Expression.Disjunction正是我所需要的。谢谢! – csano 2011-05-04 18:45:09