我有以下nHibernate查询,它可以很好地拉取实体并急切地获取其子集合。
var contactInfo = session.QueryOver<PeopleInfo>()
.Fetch(x => x.Addresses).Eager
.Fetch(x => x.EmailAddresses).Eager
.Fetch(x => x.PhoneNumbers).Eager
.Where(x => x.Id == contactInfoId)
.SingleOrDefault();
现在,让我们在地址中说有一个名为Active的字段, 有没有办法在一次通话中返回所有活动地址?
我可以在事后过滤掉它,我只是想知道是否有 一种通过查询来实现的方法。
谢谢!
答案 0 :(得分:3)
是的,您可以执行此操作,但需要在QueryOver查询中包含一些联接。
在幕后,.Fetch
正在生成一堆LEFT JOIN
来恢复PeopleInfo
的完整列表,而不会排除那些没有任何关联集合的人热切地抓住了。
您可以通过自己执行左连接来覆盖连接的执行方式。
例如,如果您想获取所有PeopleInfo
,并且只想获取Active
的地址,则可以执行以下操作:
Address addressAlias;
var addressRestriction = Restrictions.Where(() => address.Active);
session.QueryOver<PeopleInfo>()
.Left.JoinQueryOver(
pi => pi.Addresses, () => addressAlias, addressRestriction)
.Fetch(x => x.Addresses).Eager
.Fetch(x => x.EmailAddresses).Eager
.Fetch(x => x.PhoneNumbers).Eager
.Where(x => x.Id == contactInfoId)
.SingleOrDefault();
现在,由于您JOIN
Address
并选择了整个PeopleInfo
实体,因此您实际上不需要使用.Fetch
来撤回所有实体Address
字段。
session.QueryOver<PeopleInfo>()
.Left.JoinQueryOver(
x => x.Addresses, () => addressAlias, addressRestriction)
.Fetch(x => x.EmailAddresses).Eager
.Fetch(x => x.PhoneNumbers).Eager
.Where(x => x.Id == contactInfoId)
.SingleOrDefault();
Address
子句中包含SELECT
列,因为您已加入Address
并正在选择整个PeopleInfo
类。
这两者都生成相同的SQL,但您应该在分析器中进行验证。看起来应该是这样的:
SELECT this_.* -- All PeopleInfo columns
addressali1_.*, -- All Address columns
emailaddre4_.* -- All email address columns
FROM PeopleInfo this_
LEFT OUTER JOIN address addressali1_
ON this_.id = addressali1_.personid
AND ( addressali1_.active = 1)
LEFT OUTER JOIN emailaddress emailaddre4_
ON this_.id = emailaddre4_.personid
WHERE this_.id = <your id>