使用Criteria API在NHibernate中选择子查询

本文关键字:选择 查询 NHibernate Criteria API 使用 | 更新日期: 2023-09-27 18:00:54

所以我有一个SQL查询,其结构如下:

select p.* from
(
    select max([price]) as Max_Price,
    [childId] as childNodeId
    from [Items] group by [childId]
) as q inner join [Items] as p on p.[price] = q.[Max_Price] and p.[childId] = q.[childNodeId]

我需要使用Criteria API在NHibernate中重新创建这个查询。我尝试使用Subqueries API,但似乎需要内部查询返回一列,以检查与外部查询中的属性是否相等。然而,我返回了两个。我已经读到这可以通过HQL API实现,但我需要使用Criteria API来实现,因为我们将动态生成这样的查询。这里有人能指引我朝正确的方向走吗?

使用Criteria API在NHibernate中选择子查询

我通过稍微调整原始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版本(。

如果这对你有用,请告诉我。