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

NHibernate中C#调用SetFirstResult()查询第一页时崩溃

问题分析与解决

首先明确:*(page-1)sizeToShowOnOnePage的分页计算是正确的,第一页page=1时起始位置为0,这不是导致执行失败的原因。

你遇到的问题根源在于NHibernate对原生SQL分页的处理逻辑:当你的查询外层包含SELECT *和窗口函数COUNT(*) OVER()时,NHibernate自动添加Top(?)的方式会破坏原有查询结构,导致语法错误。

具体解决方法

1. 替换SELECT *为明确字段列表

避免使用SELECT *,手动列出所有需要返回的字段(包括子查询中的字段和TotalCount)。NHibernate对明确字段的解析更稳定,能正确生成符合语法的分页SQL:

string queryString = @"
    SELECT 
        subquery.Field1,
        subquery.Field2,
        -- 列出所有子查询中的字段
        COUNT(*) OVER() AS TotalCount
    FROM (" + sb.ToString() + @") AS subquery 
    ORDER BY PlanTranDate";

2. 手动编写分页SQL(推荐)

如果必须保留原生SQL结构,直接在SQL中手动实现分页逻辑,跳过NHibernate的SetFirstResult和SetMaxResults,避免其自动修改SQL:

int offset = (page - 1) * sizeToShowOnOnePage;
string queryString = $@"
    SELECT *
    FROM (
        SELECT 
            *,
            COUNT(*) OVER() AS TotalCount
        FROM ({sb.ToString()}) AS subquery 
        ORDER BY PlanTranDate
    ) AS paged_data
    OFFSET {offset} ROWS FETCH NEXT {sizeToShowOnOnePage} ROWS ONLY";

(注:此语法适用于SQL Server 2012+,如果是其他数据库,需替换为对应分页语法,比如MySQL用LIMIT offset, size)

3. 改用NHibernate查询API

放弃原生SQL,使用NHibernate的QueryOver或Criteria API构建查询,让NHibernate自动处理分页和结果映射,能从根源避免这类原生SQL的兼容问题:

var query = session.QueryOver<YourEntity>()
    .SelectList(list => list
        .Select(x => x.Field1)
        .Select(x => x.Field2)
        // 添加所有需要的字段
        .SelectProjections(Projections.RowCountInt64().WithAlias(() => abcListVo.TotalCount))
    )
    .OrderBy(x => x.PlanTranDate).Asc
    .TransformUsing(Transformers.AliasToBean<abcListVo>())
    .Skip((page - 1) * sizeToShowOnOnePage)
    .Take(sizeToShowOnOnePage);

rvalue = query.List<abcListVo>();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:28:11