Можно ли добавить .Where () к свойству дочерней коллекции, используя nhibernate linq? - PullRequest
5 голосов
/ 30 декабря 2010

у меня есть этот запрос, который я выполняю, чтобы выполнить предварительное объединение между этими таблицами:

Таблица - столбцы
- Проект - идентификатор, имя, описание
- ProjectSponsor (таблица моста) - идентификатор, спонсор, проект, isPrimarySponsor
- Спонсор - id, первый, последний

Вот запрос nhibernate 3 linq, который я выполняю для объединения:

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

как мне добавить предложение where, чтобы включить только спонсора, где спонсорName = "Джо"

я помню, что выборка всегда происходила в конце nhibernate linq-запроса, но мне кажется, что мне нужно сделать где после "ThenFetch", чтобы эта работа работала?

Может кто-нибудь, пожалуйста, дайте мне знать, как я могу добавить эквивалент «условия предложения» на Спонсора

Примечание:

У меня не может быть простого прямого сопоставления «многие ко многим» из Проекта в Спонсора из-за поля « isPrimarySponsor », которое необходимо указать в таблице моста.

Ответы [ 2 ]

7 голосов
/ 19 января 2011

Сначала позвольте мне показать мое понимание того, чего вы пытаетесь достичь. Вы хотите получить ВСЕ проекты, и в эти проекты вы хотите получить их соответствующих 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, в которых Джо является спонсором.

Я не уверен, что это лучший подход, но надеюсь, что он поможет.

0 голосов
/ 30 декабря 2010

Я создаю запросы 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...