NHibernate коррелированный подзапрос с использованием ICriteria - PullRequest
2 голосов
/ 25 октября 2010

Я проводил некоторую работу по оценке NHibernate для будущего проекта и прорабатываю некоторые варианты использования, чтобы посмотреть, как он работает.Я еще не смог найти способ выразить следующий запрос с помощью API Criteri.

Две довольно простые таблицы (сокращены для целей данного примера)

CREATE TABLE Person
(
    PersonNo  INT,
    BirthDate DATETIME
)

CREATE TABLE PersonDetails
(
    PersonNo  INT,
    FirstName VARCHAR(30),
    Surname   VARCHAR(30)
)

И запрос ...

SELECT P.PersonNo, P.FirstName, P.Surname
FROM Persons P
JOIN PersonDetails PD
  ON PD.PersonNo = P.PersonNo
 AND EffDate =
    (
        SELECT MAX(EffDate)
        FROM PersonDetails
        WHERE PersonNo = PD.PersonNo
    )
WHERE P.PersonNo = 1

По сути, я просто пытаюсь свести основную запись о человеке и последнюю версию о человеке в один объект.Я смог сделать это достаточно легко, используя HQL, но не смог заставить работать коррелированный подзапрос.

Вот моя попытка.

var pdSub = DetachedCriteria.For<PersonRevision>("pdSub")
    .SetProjection(
        Projections.ProjectionList()
            .Add(Projections.Max("EffDate").As("MaxEffDate"))
            .Add(Projections.Property("Person.PersonNo").As("PersonNo")) 
            .Add(Projections.GroupProperty("Person.PersonNo")))
    .Add(Expression.EqProperty("pdSub.Person.PersonNo", "p.PersonNo"));    

var p =
    session.CreateCriteria<Person>("p")                                                
        .Add(Restrictions.Eq("p.PersonNo", 1))
        .Add(Subqueries.Eq("p.PersonNo", pdSub))
        .List();  

Подзапрос pdSub уже определяет отношение (по PersonNo), нокласс подзапросов требует определения другого отношения (например, Eq)?

Любая помощь будет оценена.

Спасибо, Джон

1 Ответ

5 голосов
/ 11 ноября 2010

Для демонстрации я добавил EffDate в обе таблицы. Надеюсь, это соответствует вашей модели и демонстрирует этот тип соединения соответственно.

DetachedCriteria subQuery = DetachedCriteria
    .For<PersonDetails>("pd")
    .SetProjection(Projections.Max("pd.EffDate"))
    .Add(Restrictions.EqProperty("pd.PersonId", "p.PersonId"));

IList results = Session
    .CreateCriteria(typeof(Person), "p")
    .SetProjection(Projections.ProjectionList()
        .Add(Projections.Property("p.PersonId").As("PersonId"))
        .Add(Projections.Property("p.EffDate").As("MaxEffDate")))
    .Add(Subqueries.PropertyEq("p.EffDate", subQuery))
    .List();

SQL NHibernate выбрасывает на сервер выглядит следующим образом ...

SELECT this_.PersonId as y0_, this_.EffDate as y1_ FROM Person this_ WHERE this_.EffDate = (SELECT max(this_0_.EffDate) as y0_ FROM PersonDetails this_0_ WHERE this_0_.PersonId = this_.PersonId)
...