你可以过滤nhibernate子集合吗?

时间:2015-04-16 22:18:44

标签: c# nhibernate

我有以下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的字段, 有没有办法在一次通话中返回所有活动地址?

我可以在事后过滤掉它,我只是想知道是否有 一种通过查询来实现的方法。

谢谢!

1 个答案:

答案 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>