Мне удалось решить аналогичную проблему, слегка адаптировав исходный SQL-запрос. Я закончил что-то вроде этого (псевдо-SQL-код):
SELECT p.* FROM [Items] as p
WHERE EXISTS
(
SELECT [childId] as childNodeId FROM [Items] as q
WHERE p.[childId] = q.[childNodeId]
GROUP BY q.[childId]
HAVING p.[price] = MAX(q.[price])
)
И это реализация QueryOver:
var subquery = QueryOver.Of(() => q)
.SelectList(list => list.SelectGroup(() => q.ChildId))
.Where(Restrictions.EqProperty(
Projections.Property(() => p.Price),
Projections.Max(() => q.Price)))
.And(Restrictions.EqProperty(
Projections.Property(() => p.ChildId),
Projections.Property(() => q.ChildId)));
Отсюда вам нужно только передать псевдонимы, чтобы NHibernate мог правильно разрешать сущности (псевдокод):
var filter = QueryOver.Of(() => p)
.WithSubquery.WhereExists(GetSubQuery(p, criteria...));
Надеюсь, это поможет в вашем конкретном случае.
ОБНОВЛЕНИЕ: Критерии API
var subquery = DetachedCriteria.For<Items>("q")
.SetProjection(Projections.ProjectionList()
.Add(Projections.GroupProperty("q.ChildId")))
.Add(Restrictions.EqProperty("p.Price", Projections.Max("q.Price")))
.Add(Restrictions.EqProperty("p.ChildId", "q.ChildId"));
var query = DetachedCriteria.For<Items>("p")
.Add(Subqueries.Exists(subquery));
Тем не менее, я бы порекомендовал придерживаться версии QueryOver
, она намного более интуитивна, и вы избегаете магических строк (особенно если вам не нужно обновлять версию NH).
Пожалуйста, дайте мне знать, если это работает для вас.