考虑一个Person
表,其中每个名称(第一个、最后一个、中间…)都存储在一个单独的表PersonName
中,我想为每个Person选择两个不同的名称。
SQL看起来像:
SELECT firstName.VALUE, lastName.VALUE
FROM person p
inner join personName firstName on p.ID=firstName.PersonId AND firstName.Type='FIRSTNAME'
inner join personName lastName on p.ID=lastName.PersonId AND lastName.Type='LASTNAME'
我想用NHibernate创建这个查询。我的第一次尝试是使用QueryOver
,但遇到了一个NHibernate问题。
在那之后,我尝试了SelectSubQuery
,但它真的很慢+它使过滤/排序更加困难。
这有可能吗?还是我需要恢复到自己构建SQL?
更新:
这必须是动态的,我之前不知道是哪个PersonName.Type我必须选择。
附言:我在这里使用Person+Names作为一个简化的例子。
您可以按类层次结构创建一个表。这意味着您将创建一个PersonName类,然后为First和Last name类型(即PersonFirstName、PersonLastName类)创建子类。然后进行映射并为Type属性定义描述符值。
<class name="PersonName" table="PersonName">
<id name="Id" type="Int64">
<generator class="native"/>
</id>
<discriminator column="Type" type="String"/>
<property name="Value" />
...
<subclass name="PersonFirstName" discriminator-value="FIRSTNAME">
...
</subclass>
<subclass name="PersonLastName " discriminator-value="LASTNAME">
...
</subclass>
</class>
然后,您的Person类将具有对PersonFirstName和PersonLastName的引用。
我希望这种表格设计有充分的理由,因为对于名称这样一个基本的东西来说,它似乎过于复杂了。
更新
为了进一步限制语言,你可以将它们更改为集合,然后在加入时使用一个额外的条件。
PersonFirstName fn = null;
var q = QueryOver<Person>()
.JoinAlias(
x => x.FirstNames,
() => fn,
JoinType.InnerJoin,
Restrictions.Where<PersonFirstName>(x => x.Language = "en"));
因为看起来这在NHibernate中不会被修复(在他们的错误跟踪系统中标记为"琐碎"),所以我实际上从Query Over切换到了HQL。
对HQL执行完全相同的操作不会触发错误,并且可以按预期工作。