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

leo*_*ora 5 c# linq nhibernate fluent-nhibernate

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

表 - 列
- 项目 - id,名称,描述
- ProjectSponsor(桥表) - id,sponsorid,projectid,isPrimarySponsor
- Sponsor - id,first,last

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

 IEnumerable<Project> list = Session.Query<Project>().FetchMany(r => r.ProjectSponsors).ThenFetch(r => r.Sponsor);
Run Code Online (Sandbox Code Playgroud)

如何添加where子句只包括赞助商名称="Joe"的赞助商

我记得看到fetch总是在nhibernate linq查询的结尾处出现但似乎ai需要在"ThenFetch"之后执行此操作吗?

任何人都可以让我知道如何在赞助商上添加"where子句"等价物

注意:

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

Fra*_*čik 7

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

因此,如果项目没有"Joe"赞助商,那么其ProjectSponsors集合将为空.是对的吗?

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

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

Session.Query<Project>().FetchMany(r => r.ProjectSponsors).ThenFetch(r => r.Sponsor).Where(s => s.Name == "Joe")
Run Code Online (Sandbox Code Playgroud)

它会产生什么样的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'
Run Code Online (Sandbox Code Playgroud)

然而,这将导致仅选择那些至少有一个名为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>
Run Code Online (Sandbox Code Playgroud)

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

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

这将生成这样的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
Run Code Online (Sandbox Code Playgroud)

这将选择所有项目,但仅限于他们只有Joe作为赞助商的ProjectSponsor组合.

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