NHibernate로 어떻게 페이징을 할 수 있습니까?


107

예를 들어, 표시된 행 수에 필요한 데이터만으로 ASP.NET 웹 페이지의 gridview 컨트롤을 채우려 고합니다. NHibernate는 이것을 어떻게 지원할 수 있습니까?

답변:


111

ICriteriaSetFirstResult(int i)당신이 얻을하고자하는 첫 번째 항목의 인덱스 (페이지에서 기본적으로 첫 번째 데이터 행) 표시 방법.

또한 SetMaxResults(int i)가져 오려는 행 수 (예 : 페이지 크기)를 나타내는 메서드 도 있습니다 .

예를 들어이 기준 객체는 데이터 그리드의 처음 10 개 결과를 가져옵니다.

criteria.SetFirstResult(0).SetMaxResults(10);

1
이것은 Linq (NH에 대한) 구문이 어차피 어떻게 생겼을 지 꽤 비슷합니다.
MotoWilliams

13
호출기를 렌더링하려면 총 행 수를 검색하기 위해 별도의 트랜잭션을 실행해야한다는 점에 유의하는 것이 중요합니다.
Kevin Pang

1
SQL Server에서 SELECT TOP 쿼리를 수행합니다. SetFirstResult (1) .SetMaxResult (2);
Chris S

4
이전 댓글은 NHibernate.Dialect.MsSql2005Dialect가 아닌 NHibernate.Dialect.MsSql2000Dialect를 사용하고 있습니다.
Chris S

IQuery는 동일한 기능을 가지고 있으므로 HQL에서도 사용할 수 있습니다.
goku_da_master

87

또한 NHibernate의 Futures 기능을 활용하여 쿼리를 실행하여 단일 쿼리의 실제 결과뿐만 아니라 총 레코드 수를 얻을 수도 있습니다.

 // Get the total row count in the database.
var rowCount = this.Session.CreateCriteria(typeof(EventLogEntry))
    .Add(Expression.Between("Timestamp", startDate, endDate))
    .SetProjection(Projections.RowCount()).FutureValue<Int32>();

// Get the actual log entries, respecting the paging.
var results = this.Session.CreateCriteria(typeof(EventLogEntry))
    .Add(Expression.Between("Timestamp", startDate, endDate))
    .SetFirstResult(pageIndex * pageSize)
    .SetMaxResults(pageSize)
    .Future<EventLogEntry>();

총 레코드 수를 얻으려면 다음을 수행하십시오.

int iRowCount = rowCount.Value;

Futures가 제공하는 것에 대한 좋은 토론이 여기에 있습니다 .


3
이것은 훌륭합니다. Futures는 다중 기준의 구문 적 복잡성없이 다중 기준과 똑같이 작동합니다.
DavGarcia

Futures에 대한 게시물을 읽은 후 모든 데이터베이스 쿼리에 Future를 사용해야하는지 궁금합니다. 단점은 무엇입니까? :)
hakksor 2011 년

46

NHibernate 3 이상에서 다음을 사용할 수 있습니다 QueryOver<T>.

var pageRecords = nhSession.QueryOver<TEntity>()
            .Skip((PageNumber - 1) * PageSize)
            .Take(PageSize)
            .List();

다음과 같이 결과를 명시 적으로 정렬 할 수도 있습니다.

var pageRecords = nhSession.QueryOver<TEntity>()
            .OrderBy(t => t.AnOrderFieldLikeDate).Desc
            .Skip((PageNumber - 1) * PageSize)
            .Take(PageSize)
            .List();

.Skip(PageNumber * PageSize)이렇게하면 페이지 크기가 10이면 처음 10 개 행을 검색하지 않습니다. 수식을 수정하기 위해 편집 중입니다. 개념적으로, 가정하면 PageNumber0이 안하면 그것은 1 이상 높아야
아 미트 조시

31
public IList<Customer> GetPagedData(int page, int pageSize, out long count)
        {
            try
            {
                var all = new List<Customer>();

                ISession s = NHibernateHttpModule.CurrentSession;
                IList results = s.CreateMultiCriteria()
                                    .Add(s.CreateCriteria(typeof(Customer)).SetFirstResult(page * pageSize).SetMaxResults(pageSize))
                                    .Add(s.CreateCriteria(typeof(Customer)).SetProjection(Projections.RowCountInt64()))
                                    .List();

                foreach (var o in (IList)results[0])
                    all.Add((Customer)o);

                count = (long)((IList)results[1])[0];
                return all;
            }
            catch (Exception ex) { throw new Exception("GetPagedData Customer da hata", ex); }
      }

데이터를 페이징 할 때 MultiCriteria에서 형식화 된 결과를 얻는 또 다른 방법이 있습니까? 아니면 모두가 저처럼 똑같은 일을합니까?

감사


23

Ayende 의이 블로그 게시물 에서 논의 된 것처럼 Linq를 NHibernate에 사용 하는 것은 어떻습니까?

코드 샘플 :

(from c in nwnd.Customers select c.CustomerID)
        .Skip(10).Take(10).ToList(); 

그리고 여기에 페이징 구현을 포함하여 NHibernate 를 사용한 데이터 액세스 에 대한 NHibernate 팀 블로그의 자세한 게시물이 있습니다.


NHibernate에에 참고 LINQ가있는 contrib 패키지에와 NHibernate에 2.0 릴리스에 포함되어 있지 않습니다
리처드

11

대부분의 경우 GridView에서 데이터 조각과 쿼리와 일치하는 총 데이터 양의 총 행 수 (rowcount)를 표시하려고합니다.

MultiQuery를 사용하여 Select count (*) 쿼리와 .SetFirstResult (n) .SetMaxResult (m) 쿼리를 한 번의 호출로 데이터베이스로 보내야합니다.

결과는 데이터 조각 용과 개 수용으로 하나씩 2 개의 목록을 보유하는 목록입니다.

예:

IMultiQuery multiQuery = s.CreateMultiQuery()
    .Add(s.CreateQuery("from Item i where i.Id > ?")
            .SetInt32(0, 50).SetFirstResult(10))
    .Add(s.CreateQuery("select count(*) from Item i where i.Id > ?")
            .SetInt32(0, 50));
IList results = multiQuery.List();
IList items = (IList)results[0];
long count = (long)((IList)results[1])[0];

6

페이지 매김을 처리하기 위해 특정 구조를 만드는 것이 좋습니다. (저는 Java 프로그래머이지만 매핑하기 쉽습니다) :

public class Page {

   private List results;
   private int pageSize;
   private int page;

   public Page(Query query, int page, int pageSize) {

       this.page = page;
       this.pageSize = pageSize;
       results = query.setFirstResult(page * pageSize)
           .setMaxResults(pageSize+1)
           .list();

   }

   public List getNextPage()

   public List getPreviousPage()

   public int getPageCount()

   public int getCurrentPage()

   public void setPageSize()

}

구현을 제공하지는 않았지만 @Jon이 제안한 방법을 사용할 수 있습니다 . 여기에 좋은 토론 이 있습니다.


0

두 가지 기준을 정의 할 필요가 없으며 하나를 정의하고 복제 할 수 있습니다. nHibernate 기준을 복제하려면 간단한 코드를 사용할 수 있습니다.

var criteria = ... (your criteria initializations)...;
var countCrit = (ICriteria)criteria.Clone();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.