2010-10-24 6 views
2

J'ai fait un travail d'évaluation de NHibernate pour un projet à venir et je travaille sur quelques cas d'utilisation pour voir comment elle fonctionne. Je n'ai pas encore été en mesure de trouver un moyen d'exprimer la requête suivante en utilisant l'API Criteri.Sous-requête corrélée par NHibernate en utilisant ICriteria

Deux tables assez basiques (coupés dans le but de cet exemple)

CREATE TABLE Person 
(
    PersonNo INT, 
    BirthDate DATETIME 
) 

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

Et la requête ...

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 

Fondamentalement, je suis juste essayer d'aplatir la personne fiche de et le dernier enregistrement de révision de personne dans un objet. J'ai été capable de le faire assez facilement en utilisant HQL mais je n'arrive pas à faire fonctionner la sous-requête corrélée.

Voici ma tentative.

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(); 

La sous-requête pdSub définit déjà la relation (par PersonNo), mais la classe des sous-requêtes nécessite une autre relation à définir (par exemple l'équation)?

Toute aide serait appréciée.

Merci, John

Répondre

5

Aux fins d'une démonstration que j'ai ajouté EffDate aux deux tables. J'espère que cela correspond à votre modèle et démontre ce type de jointure de manière appropriée.

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(); 

Le SQL NHibernate est de lancer sur le serveur ressemble à ceci ...

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) 
Questions connexes