Сначала позвольте мне показать мое понимание того, чего вы пытаетесь достичь. Вы хотите получить ВСЕ проекты, и в эти проекты вы хотите получить их соответствующих ProjectSponsors, которые включают в себя Sponsors, но вам нужны только такие ProjectSponsors, у которых есть Sponsor с определенным именем.
Таким образом, если для проекта нет спонсора "Джо", его коллекция 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'
Однако это приведет к выбору только тех проектов, в которых есть хотя бы один спонсор по имени Джо.
На самом деле вы хотите отфильтровать ProjectSponsors, чтобы выбрать только тех, чей Sponsor по имени Joe.
Теперь я не знаю, является ли это приемлемым для вас решением, но я бы так и сделал. Я бы определил и установил фильтр в своем сопоставлении для ассоциации ProjectSponsors в сущности Project следующим образом:
<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
, который выберет все проекты, но для них будут только такие комбинации ProjectSponsor, в которых Джо является спонсором.
Я не уверен, что это лучший подход, но надеюсь, что он поможет.