NHibernate 3分页并确定总行数

cs0*_*815 12 nhibernate

我已经阅读了NHibernate 3允许在执行分页查询时(在一个数据库查询中)确定记录总数的某处(不能记住何处和如何).这是正确的吗?

我有这个代码:

public IEnumerable<X> GetOrganisms(int PageSize, int Page, out int total)
{
    var query = (from e in Session.Query<X>() select e).AsQueryable();

    return query.Skip((Page - 1) * PageSize).Take(PageSize).ToList();
}
Run Code Online (Sandbox Code Playgroud)

并希望尽可能有效地初始化"总数".

谢谢.

基督教

PS:

潜在的"解决方案"?:

Total = (int) Session.CreateCriteria<X>()
.SetProjection(Projections.RowCount())
.FutureValue<Int32>().Value;

var query = (from e in Session.Query<X>() select e).AsQueryable();

return query.Skip((Page - 1) * PageSize).Take(PageSize).ToList();
Run Code Online (Sandbox Code Playgroud)

cod*_*ion 25

您的潜在解决方案将在一个事务中处理,但将是两个db调用.如果您必须只有一个数据库调用,则应使用同步建议的多查询/未来查询.有关未来语法的更多信息,请查看此文章:http://ayende.com/blog/3979/nhibernate-futures.

以下是完成场景的几种方法......

QueryOver(2分贝调用):
var query = session.QueryOver<Organism>();
var result = query
    .Skip((Page - 1) * PageSize)
    .Take(PageSize)
    .List();
var rowcount = query.RowCount();
Run Code Online (Sandbox Code Playgroud)

使用100个生物的样本集,并查询生物11-20,这里是发送到db的两个查询:

SELECT TOP (@p0) Id0_0_, Title0_0_ FROM (SELECT this_.Id as Id0_0_, this_.Title as Title0_0_, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM Organism this_) as query WHERE query.__hibernate_sort_row > @p1 ORDER BY query.__hibernate_sort_row;@p0 = 10 [Type: Int32 (0)], @p1 = 10 [Type: Int32 (0)]
SELECT count(*) as y0_ FROM Organism this_
Run Code Online (Sandbox Code Playgroud) QueryOver(使用Future进行1分贝调用):
var query = session.QueryOver<Organism>()
    .Skip((Page - 1) * PageSize)
    .Take(PageSize)
    .Future<Organism>();
var result = query.ToList();
var rowcount = session.QueryOver<Organism>()
    .Select(Projections.Count(Projections.Id()))
    .FutureValue<int>().Value;
Run Code Online (Sandbox Code Playgroud)

查询与以前相同的数据集,这是生成的查询:

SELECT TOP (@p0) Id0_0_, Title0_0_ FROM (SELECT this_.Id as Id0_0_, this_.Title as Title0_0_, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM Organism this_) as query WHERE query.__hibernate_sort_row > @p1 ORDER BY query.__hibernate_sort_row;SELECT count(this_.Id) as y0_ FROM Organism this_;;@p0 = 10 [Type: Int32 (0)], @p1 = 10 [Type: Int32 (0)]
Run Code Online (Sandbox Code Playgroud) 标准(使用Future进行1分贝调用):
var criteria = session.CreateCriteria<Organism>()
    .SetFirstResult((Page - 1) * PageSize)
    .SetMaxResults(PageSize)
    .Future<Organism>();
var countCriteria = session.CreateCriteria<Organism>()
    .SetProjection(Projections.Count(Projections.Id()))
    .FutureValue<int>().Value;
Run Code Online (Sandbox Code Playgroud)

同样,查询同一组数据,在同一查询中使用未来结果的条件:

SELECT TOP (@p0) Id0_0_, Title0_0_ FROM (SELECT this_.Id as Id0_0_, this_.Title as Title0_0_, ROW_NUMBER() OVER(ORDER BY CURRENT_TIMESTAMP) as __hibernate_sort_row FROM Organism this_) as query WHERE query.__hibernate_sort_row > @p1 ORDER BY query.__hibernate_sort_row;SELECT count(this_.Id) as y0_ FROM Organism this_;;@p0 = 10 [Type: Int32 (0)], @p1 = 10 [Type: Int32 (0)]
Run Code Online (Sandbox Code Playgroud)

请注意,所有三种查询样式都会产生完全相同的查询.未来的语法只允许NHibernate进行一次数据库调用,而不是两次.

如果您使用的是NHibernate 3,我认为最优雅的方法是使用新的QueryOver语法.(您在建议的解决方案中使用了旧的NHibernate.Linq语法.您最好学习QueryOver语法.)