You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用NHibernate编写含公共表表达式(CTE)的查询?

将SQL Server查询改写为NHibernate查询

原SQL核心逻辑为:筛选出2023-06-08当天、ABC='foo'且XYZ=123的Items记录,按ItemGuid分组后取每组中Version最大的最新一条。以下提供几种NHibernate实现方式:

方法1:使用HQL(支持窗口函数,NHibernate 5.1+)

NHibernate 5.1及以上版本支持窗口函数,可直接复刻原SQL逻辑:

var hql = @"
WITH MostRecentToday AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY ItemGuid ORDER BY Version DESC) AS rn
    FROM Items
    WHERE Cast(Timestamp As date) = :dateFilter and ABC = :abcValue and XYZ = :xyzValue
)
SELECT *
FROM MostRecentToday
WHERE rn = 1";

var session = sessionFactory.OpenSession();
var result = session.CreateQuery(hql)
    .SetParameter("dateFilter", new DateTime(2023, 6, 8))
    .SetParameter("abcValue", "foo")
    .SetParameter("xyzValue", 123)
    .List<Item>();

方法2:使用QueryOver API

若偏好强类型查询,可通过子查询实现等价逻辑(适配不支持窗口函数的旧版NHibernate):

var session = sessionFactory.OpenSession();

// 子查询:获取每个ItemGuid对应的最大Version值
var maxVersionSubquery = QueryOver.Of<Item>()
    .Select(Projections.Max<Item>(i => i.Version))
    .Where(Restrictions.EqProperty("ItemGuid", "outer.ItemGuid"))
    .And(Restrictions.Eq("ABC", "foo"))
    .And(Restrictions.Eq("XYZ", 123))
    .And(Restrictions.Where<Item>(i => i.Timestamp.Date == new DateTime(2023, 6, 8)));

// 主查询:关联子查询筛选每组最新记录
var result = session.QueryOver<Item>("outer")
    .Where(Restrictions.Eq("ABC", "foo"))
    .And(Restrictions.Eq("XYZ", 123))
    .And(Restrictions.Where<Item>(i => i.Timestamp.Date == new DateTime(2023, 6, 8)))
    .WithSubquery.WhereProperty(i => i.Version).Eq(maxVersionSubquery)
    .List<Item>();

注意:此方式仅在ItemGuid与Version组合唯一时生效,若同一ItemGuid、同一Version存在多条记录,需额外添加排序字段的子查询处理。

方法3:使用原生SQL查询

若HQL窗口函数支持存在问题,可直接执行原生SQL并映射到实体:

var session = sessionFactory.OpenSession();
var sql = @"
WITH MostRecentToday AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY ItemGuid ORDER BY Version DESC) AS rn
    FROM Items
    WHERE Cast(Timestamp As date) = @dateFilter and ABC = @abcValue and XYZ = @xyzValue
)
SELECT *
FROM MostRecentToday
WHERE rn = 1";

var result = session.CreateSQLQuery(sql)
    .AddEntity(typeof(Item))
    .SetParameter("dateFilter", new DateTime(2023, 6, 8))
    .SetParameter("abcValue", "foo")
    .SetParameter("xyzValue", 123)
    .List<Item>();

内容的提问来源于stack exchange,提问作者Mike

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:42:39