2010-10-24 2 views
2

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

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

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), но класс подзапросов требует другого отношения должны быть определены (например, уравнение)?

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

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

ответ

5

Для целей демо я добавил 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) 
Смежные вопросы