NHibernate 3 paging and determining the total number of rows

后端 未结 3 1020
生来不讨喜
生来不讨喜 2021-01-31 06:06

I have read somewhere (can\'t remeber where and how) that NHibernate 3 allows the determination of the total number of records whilst performing a paged query (in one database q

3条回答
  •  离开以前
    2021-01-31 06:47

    Your potential solution will be handled in one transaction, but will be two db calls. If you must have only one db call, you should use a multiquery/future query as peer suggested. For more information on the future syntax, check out this post: http://ayende.com/blog/3979/nhibernate-futures.

    Here are a few ways to accomplish your scenario...

    QueryOver (2 db calls):
    var query = session.QueryOver();
    var result = query
        .Skip((Page - 1) * PageSize)
        .Take(PageSize)
        .List();
    var rowcount = query.RowCount();
    

    With a sample set of 100 Organisms, and querying for the organisms 11-20, here are the two queries sent to the 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_
    
    QueryOver (1 db call with Future):
    var query = session.QueryOver()
        .Skip((Page - 1) * PageSize)
        .Take(PageSize)
        .Future();
    var result = query.ToList();
    var rowcount = session.QueryOver()
        .Select(Projections.Count(Projections.Id()))
        .FutureValue().Value;
    

    Querying for the same set of data as before, this is the query that is generated:

    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)]
    
    Criteria(1 db call with Future):
    var criteria = session.CreateCriteria()
        .SetFirstResult((Page - 1) * PageSize)
        .SetMaxResults(PageSize)
        .Future();
    var countCriteria = session.CreateCriteria()
        .SetProjection(Projections.Count(Projections.Id()))
        .FutureValue().Value;
    

    Again, querying for the same set of data, criteria with future results in the same query:

    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)]
    

    Notice that all three query styles result in the same exact queries. The future syntax simply allows NHibernate to make one database call rather than two.

    If you are using NHibernate 3, I think the most elegant way to handle this is using the new QueryOver syntax. (You used the old NHibernate.Linq syntax in your proposed solution. You are better off to learn the QueryOver syntax instead.)

提交回复
热议问题