Domanda

I have to implement something like this using NHibernate

DetachedCriteria maxDateQuery = DetachedCriteria.forClass(FtpStatus.class);
ProjectionList proj = Projections.projectionList();
proj.add(Projections.max("datetime"));
proj.add(Projections.groupProperty("connectionid"));
maxDateQuery.setProjection(proj);

Criteria crit = s.createCriteria(FtpStatus.class);
crit.add(Subqueries.propertiesEq(new String[] {"datetime", "connectionid"}, maxDateQuery));

List<FtpStatus> dtlList = crit.list();

(This snippet is from Hibernate criteria query using Max() projection on key field and group by foreign primary key)

My problem is that Nhibernate doesn't implement "Subqueries.propertiesEq" which is used in this row:

crit.add(Subqueries.propertiesEq(new String[] {"datetime", "connectionid"}, maxDateQuery));

Could you please suggest a workaround?

È stato utile?

Soluzione

The answer here is (talking about NHibernate) to use EXISTS instead of IN. The query would look like this

// the below outer query, has essential feature
// ALIAS name "outer"
// and this is used here, in the "subquery"
var maxDateQuery = DetachedCriteria.For<MyEntity>("myEntity")
    .SetProjection(
        Projections.ProjectionList()
        .Add(Projections.GroupProperty("MyId"))
        .Add(Projections.Max("MyDate"))
        )
        .Add(Restrictions.EqProperty(
        Projections.Max("MyDate"),
        Projections.Property("outer.MyDate")) // compare inner MAX with outer current
        )
        .Add(Restrictions.EqProperty("MyId", "outer.MyId")) // inner and outer must fit
    ;

// here ... the "outer" is essential, because it is used in the subquery
var list = session.CreateCriteria<Contact>("outer")
    .Add(Subqueries.Exists(maxDateQuery))
    ... // e.g. paging
    .List<MyEntity>();

And that will create query like this:

FROM [MyEntityTable] outer
WHERE exists 
(
  SELECT  myEntity.MyId
    , max(myEntity.MyDate) 
   FROM [MyEntityTable] myEntity
   WHERE    myEntity.MyId         = outer.MyId   // matching ID
   GROUP BY myEntity.MyId
   HAVING   max(myEntity.MyDate)  = outer.MyDate // matching max and current date
)

The same type of query (even more complex) in a QueryOver syntax can be found here:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top