你能过滤 nhibernate 子集合吗?
Can you filter nhibernate sub collection?
我有以下 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();
现在,假设在 Addresses 中有一个名为 Active 的字段,
有没有办法在一次调用中 return 所有活动地址?
我可以事后过滤掉,我只是想知道是否有
一种通过查询完成的方法。
谢谢!
是的,您可以这样做,但您需要在 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
class。
它们都生成相同的 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>
我有以下 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();
现在,假设在 Addresses 中有一个名为 Active 的字段, 有没有办法在一次调用中 return 所有活动地址?
我可以事后过滤掉,我只是想知道是否有 一种通过查询完成的方法。
谢谢!
是的,您可以这样做,但您需要在 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
class。
它们都生成相同的 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>