是否可以使用nhibernate linq在子集合属性上添加.Where()?

时间:2010-12-30 13:00:44

标签: c# linq nhibernate fluent-nhibernate

我有这个查询,我正在运行这些表之间的前期连接:

表 - 列
- 项目 - ID,名称,说明
- ProjectSponsor (桥牌表) - id,sponsorid,projectid,isPrimarySponsor
- 赞助商 - id,first,last

这是我正在运行的nhibernate 3 linq查询:

 IEnumerable<Project> list = Session.Query<Project>().FetchMany(r => r.ProjectSponsors).ThenFetch(r => r.Sponsor);

如何添加where子句以仅包含sponsorName =“Joe”

的赞助商

我记得看到fetch总是在nhibernate linq查询的结尾处出现但似乎我需要在“ThenFetch”之后执行此操作才能使其工作?

任何人都可以告诉我如何在赞助商上添加“where子句”等同物

注意:

由于桥接表中需要“ isPrimarySponsor ”字段,我不能只是从项目到赞助商进行简单的多对多直接映射。

2 个答案:

答案 0 :(得分:7)

首先让我展示我对你想要达到的目标的理解。您想要获取所有项目,并希望获取包含赞助商的相应ProjectSponsors,但您只需要具有赞助商特定名称的ProjectSponsors。

因此,如果项目没有“Joe”赞助商,那么其ProjectSponsors集合将为空。是吗?

如果是这样,您希望在项目和赞助商之间进行左联接。此外,您希望一次性获取所有内容,这就是您要使用这些Fetch方法的原因。

据我所知,实际上没有办法在你的陈述中添加Where。但即使有,我认为它也无济于事。如果你能写:

Session.Query<Project>().FetchMany(r => r.ProjectSponsors).ThenFetch(r => r.Sponsor).Where(s => s.Name == "Joe")

它会生成什么样的SQL?像这样:

SELECT 
    * 
FROM 
    Project P
    LEFT JOIN ProjectSponsors PS ON PS.ProjectId = P.ProjectId
    LEFT JOIN Sponsors S ON S.SponsorId = PS.SponsorId
WHERE
    S.Name = 'Joe'

然而,这将导致仅选择至少有一个名为Joe的赞助商的项目。

实际上,您想要过滤ProjectSponsors,只选择那些赞助商名为Joe的人。

现在我不知道这对你来说是否是一个可以接受的解决方案,但我就是这样做的。我将在Project实体的ProjectSponsors关联映射中定义和设置一个过滤器,如下所示:

<class name="Project" table="Project">
...
<set name="ProjectSponsors" table="ProjectSponsor">
  <key column="ProjectId" />
  <one-to-many class="ProjectSponsor" />
  <filter name="SponsorName" condition="EXISTS (SELECT * FROM Sponsor where Sponsor.SponsorId = SponsorId AND Sponsor.Name=:name)" />
</set>
</class>
<filter-def name="SponsorName">
    <filter-param name="name" type="String"/>
</filter-def>

有了这个,我会在启用和设置过滤器后使用原始语句:

Session.EnableFilter("SponsorName").SetParameter("name", "Joe");
var projects = Session.Query<Project>().FetchMany(r => r.ProjectSponsors).ThenFetch(r => r.Sponsor);

这将产生这样的SQL:

SELECT 
    * 
FROM 
    Project P
    LEFT JOIN ProjectSponsors PS ON PS.ProjectId = P.ProjectId AND EXISTS (SELECT * FROM Sponsor where Sponsor.SponsorId = PS.SponsorId AND Sponsor.Name = 'Joe')
    LEFT JOIN Sponsors S ON S.SponsorId = PS.SponsorId

将选择所有项目,但仅为他们选择具有Joe作为赞助商的ProjectSponsor组合。

我不确定这是否是最佳方法,但希望它会有所帮助。

答案 1 :(得分:0)

我创建了这样的NHibernate Linq查询:

IEnumerable<Project> list = (
            from p in Session.Query<Project>()
            from s in p.Sponsors
            where s.Name == "SponsorName"
            select p)
            .FetchMany(r => r.Sponsors)
    .ThenFetch(r => r.Sponsor).ToList();