Выбор подзапросов в NHibernate с Critieria API - PullRequest
5 голосов
/ 01 июля 2011

Итак, у меня есть SQL-запрос со следующей структурой:

select p.* from
(
    select max([price]) as Max_Price,
    [childId] as childNodeId
    from [Items] group by [childId]
) as q inner join [Items] as p on p.[price] = q.[Max_Price] and p.[childId] = q.[childNodeId]

Мне нужно пересоздать этот запрос в NHibernate, используя Criteria API. Я пытался использовать API подзапросов, но, похоже, требуется, чтобы внутренний запрос возвращал один столбец, чтобы проверить равенство со свойством во внешнем запросе. Тем не менее, я возвращаю два. Я читал, что это можно сделать с помощью HQL API, но мне нужно сделать это с помощью Criteria API, так как мы собираемся динамически генерировать подобные запросы на лету. Кто-нибудь может направить меня в правильном направлении здесь?

1 Ответ

14 голосов
/ 01 июля 2011

Мне удалось решить аналогичную проблему, слегка адаптировав исходный SQL-запрос. Я закончил что-то вроде этого (псевдо-SQL-код):

SELECT p.* FROM [Items] as p
WHERE EXISTS
(
    SELECT [childId] as childNodeId FROM [Items] as q
    WHERE p.[childId] = q.[childNodeId]
    GROUP BY q.[childId] 
    HAVING p.[price] = MAX(q.[price])
)

И это реализация QueryOver:

var subquery = QueryOver.Of(() => q)
  .SelectList(list => list.SelectGroup(() => q.ChildId))
      .Where(Restrictions.EqProperty(
          Projections.Property(() => p.Price), 
          Projections.Max(() => q.Price)))
      .And(Restrictions.EqProperty(
          Projections.Property(() => p.ChildId), 
          Projections.Property(() => q.ChildId)));

Отсюда вам нужно только передать псевдонимы, чтобы NHibernate мог правильно разрешать сущности (псевдокод):

var filter = QueryOver.Of(() => p)
    .WithSubquery.WhereExists(GetSubQuery(p, criteria...));

Надеюсь, это поможет в вашем конкретном случае.

ОБНОВЛЕНИЕ: Критерии API

var subquery = DetachedCriteria.For<Items>("q")
    .SetProjection(Projections.ProjectionList()
        .Add(Projections.GroupProperty("q.ChildId")))
    .Add(Restrictions.EqProperty("p.Price", Projections.Max("q.Price")))
    .Add(Restrictions.EqProperty("p.ChildId", "q.ChildId"));

var query = DetachedCriteria.For<Items>("p")
    .Add(Subqueries.Exists(subquery));

Тем не менее, я бы порекомендовал придерживаться версии QueryOver, она намного более интуитивна, и вы избегаете магических строк (особенно если вам не нужно обновлять версию NH).

Пожалуйста, дайте мне знать, если это работает для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...