NHibernate - Выберите полные записи из агрегатов - PullRequest
2 голосов
/ 16 ноября 2011

Короче говоря: с учетом агрегированного запроса (один с Max, Min, Count и т. Д.) В NHibernate, как вы можете изменить запрос, чтобы он также возвращал полную запись , связанную с агрегированным значением?

Мой пример: у меня есть 2 таблицы: People (первичный ключ: PersonId) с отношением 1-ко-многим к Events (первичный ключ: EventId; другие столбцы: PersonId, EventDate).

Я хочу выбрать последнее событие на человека и сгенерировать список этих событий . SQL для последнего события на человека будет выглядеть примерно так: SELECT PersonId, Max(EventDate) FROM ... GROUP BY PersonId. Пока что запрос NHibernate выглядит так:

ICriteria criteria = session.CreateCriteria<Event>()
    .SetProjection(Projections.ProjectionList()
        .Add(Projections.GroupProperty("PersonId"))
        .Add(Projections.Max("EventDate"))
    );

Теперь мне действительно нужна полная информация о событии 1020 *. Одно из теоретических решений заключается в том, чтобы по существу объединить вышеуказанные критерии с таблицей Events с помощью PersonId и максимального значения EventDate (достаточно просто в простом SQL). Однако я не знаю, как это сделать в NHibernate.

Я открыт для любых предложений (HQL, LINQ и т. Д.), Если они избегают хранимых процедур и представлений и ограничены 1 или несколькими запросами. В моем случае выдача запроса на человека не будет масштабируемой или производительной.

Ответы [ 2 ]

3 голосов
/ 16 ноября 2011

Я надеюсь, что вы также открыты для QueryOver (это можно преобразовать в ICriteria) ...

Event eventAlias = null;

var topEventsByPerson = Session.QueryOver<Event>(() => eventAlias)
    .WithSubquery.WhereProperty(x => x.EventId).Eq(QueryOver.Of<Event>()
        .Where(x => x.Person == eventAlias.Person)
        .OrderBy(x => x.EventDate).Desc
        .Select(x => x.EventId)
        .Take(1))
    .List();
1 голос
/ 17 ноября 2011

Хотя я предпочитаю ответ dotjoe, я не смог его реализовать из-за исключения ArgumentNullException, возникающего при использовании псевдонима QueryOver.Я подозреваю, что это ошибка в NHibernate 3.1.

Вместо этого я нашел решение, использующее ISession.CreateSQLQuery () , где я пишу запрос в простом SQL:

var results = session.CreateSQLQuery(@"
        SELECT Events.*
        FROM Events
        join (
                SELECT MAX(EventDate) as MaxEventDate, PersonId
                FROM Events
                GROUP BY PersonId
            )
            as q_LastEventsPerPerson
            on  (Events.EventDate = q_LastEventsPerPerson.MaxEventDate)
            and (Events.PersonId = q_LastEventsPerPerson.PersonId)
    ")
    .AddEntity(typeof(Event))
    .List<Event>();

Метод AddEntity () является ключевым здесь.Это вызывает автоматическое сопоставление результатов с объектами типа Событие .

Я не рекомендую этот подход, если у вас нет альтернативы.

...