NHibernate使用ICriteria关联子查询

时间:2010-10-24 22:53:54

标签: nhibernate icriteria correlated-subquery

我一直在为即将到来的项目评估NHibernate做一些工作,并正在研究一些用例以了解它的表现。我还没有找到使用Criteri API表达以下查询的方法。

两个相当基本的表(为了这个例子的目的而减少)

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),但是Subqueries类需要定义另一个关系(例如Eq)?

任何帮助都将不胜感激。

谢谢, 约翰

1 个答案:

答案 0 :(得分: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)