使用SQL Server进行NHibernate分页

使用SQL Server进行NHibernate分页,nhibernate,sql-server-2000,paging,Nhibernate,Sql Server 2000,Paging,当使用SetFirstResult(start)和SetMaxResults(count)方法来实现分页时,我注意到生成的查询只从一些表中选择top count*,而不考虑start参数,或者至少不在数据库级别。如果我指示NHibernate执行以下查询: var users = session.CreateCriteria<User>() .SetFirstResult(100) .SetMaxResult

当使用
SetFirstResult(start)
SetMaxResults(count)
方法来实现分页时,我注意到生成的查询只从一些表中
选择top count*,而不考虑
start
参数,或者至少不在数据库级别。如果我指示NHibernate执行以下查询:

var users = session.CreateCriteria<User>()
                   .SetFirstResult(100)
                   .SetMaxResults(5)
                   .List<User>();
var users=session.CreateCriteria()
.SetFirstResult(100)
.SetMaxResults(5)
.List();
105条记录将在数据库服务器和负责剥离前100条记录的应用程序之间传输。对于包含许多行的表,这可能是一个问题


我已经验证过,对于数据库,NHibernate利用
偏移量
限制
关键字在数据库级别过滤结果。我知道在SQLServer2000中没有等价的
OFFSET
关键字和Oracle的
ROWNUM
,但是有解决方法吗?SQL Server 2005/2008怎么样?

Nhibernate足够聪明,可以优化查询。如果选择前10行,它将使用
TOP
语句。如果您选择的不是第一行,则它将使用
RowNum

在sql 2000中没有
RowNum
函数,这就是为什么在常规查询中无法选择所需行数的原因。对于sql 2000,正如我所知道的那样,使用了这样的优化视图

在sql 2005/2008中,查询将仅选择所需的行


Microsoft SQL Server使用的SQL语言变体T-SQL没有
限制
子句。它有一个
selecttop{…}
修饰符,您可以看到NHibernate在SQLServer2000中利用了这个修饰符

在SQL Server 2005中,Microsoft引入了
Row_Number()over(order by{…})
函数,该函数可替代
limit
子句,您可以看到NHibernate在SQL Server 2005/2008中利用了这一点

对SQLite的查询可能如下所示

select c.[ID], c.[Name]
from [Codes] c
where c.[Key] = 'abcdef'
order by c.[Order]
limit 20 offset 40
select c.[ID], c.[Name]
from (
    select c.[ID], c.[Name], c.[Order]
        , [!RowNum] = Row_Number() over (order by c.[Order])
    from [Codes] c
    where c.[Key] = 'abcdef'
) c
where c.[!RowNum] > 40 and c.[!RowNum] <= 60
order by c.[Order]
with
    [Source] as (
        select c.[ID], c.[Name], c.[Order]
            , [!RowNum] = Row_Number() over (order by c.[Order])
        from [Codes] c
        where c.[Key] = 'abcdef'
    )
select c.[ID], c.[Name]
from [Source] c
where c.[!RowNum] > 40 and c.[!RowNum] <= 60
order by c.[Order]
而针对SQLServer2005的类似查询可能如下所示

select c.[ID], c.[Name]
from [Codes] c
where c.[Key] = 'abcdef'
order by c.[Order]
limit 20 offset 40
select c.[ID], c.[Name]
from (
    select c.[ID], c.[Name], c.[Order]
        , [!RowNum] = Row_Number() over (order by c.[Order])
    from [Codes] c
    where c.[Key] = 'abcdef'
) c
where c.[!RowNum] > 40 and c.[!RowNum] <= 60
order by c.[Order]
with
    [Source] as (
        select c.[ID], c.[Name], c.[Order]
            , [!RowNum] = Row_Number() over (order by c.[Order])
        from [Codes] c
        where c.[Key] = 'abcdef'
    )
select c.[ID], c.[Name]
from [Source] c
where c.[!RowNum] > 40 and c.[!RowNum] <= 60
order by c.[Order]

我已经验证过,在sql 2005/2008中,NHibernate使用了
row\u number()
函数。看来,使用SQL2000,我必须编写视图或存储过程才能达到同样的效果。谢谢你抽出时间。