【问题标题】:Selecting on Sub Queries in NHibernate with Critieria API使用 Criteeria API 在 NHibernate 中选择子查询
【发布时间】:2011-06-30 21:19:02
【问题描述】:

所以我有一个结构如下的 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 中重新创建此查询。我尝试使用子查询 API,但似乎需要内部查询返回单个列来检查外部查询中的属性是否相等。但是,我返回两个。我读过这可以通过 HQL API 来完成,但我需要使用 Criteria API 来完成,因为我们将动态生成这样的查询。任何人都可以在这里引导我朝着正确的方向前进吗?

【问题讨论】:

    标签: c# .net sql nhibernate


    【解决方案1】:

    我已经设法通过稍微调整原始 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 版本)。

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

    【讨论】:

    • 我有点困惑。有没有办法使用 ICriteria API 而不是 QueryOver 来做到这一点?我以前没有使用过 QueryOver,这可能是一个复杂的“第一个例子”:\
    • @GWLlosa:您能否确认我在答案中发布的 sql 对您有效并且您得到完全相同的结果?我可以尝试使用 Criteria API 重写查询,顺便说一句,您使用的是哪个版本的 NHibernate?
    • 您拥有的 SQL 和我拥有的 SQL 实际上会产生相同的行。根据 DLL 详细信息,我正在使用 NHibernate 3.1.0.4000。
    • @GWLlosa:请检查我对 Criteria API 版本的更新。
    • 很棒的工作!我缺少的关键见解是我可以在属性和投影之间添加 EqProperty 限制。我们使用 ICriteria 是为了与也使用 ICriteria 的现有代码保持一致;否则我同意; QueryOver 更干净一些。
    猜你喜欢
    • 1970-01-01
    • 2011-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多