Как вы можете делать пейджинг с NHibernate?

Например, я хочу заполнить элемент управления gridview на веб-странице ASP.NET только с данными, необходимыми для отображения количества строк. Как NHibernate может поддержать это?

Ответ 1

ICriteria имеет метод SetFirstResult(int i), который указывает индекс первого элемента, который вы хотите получить (в основном первая строка данных на вашей странице).

Он также имеет метод SetMaxResults(int i), который указывает количество строк, которые вы хотите получить (т.е. размер вашей страницы).

Например, этот объект критериев получает первые 10 результатов вашей сетки данных:

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

Ответ 2

Вы также можете воспользоваться функцией Futures в NHibernate для выполнения запроса, чтобы получить общее количество записей, а также фактические результаты в одном запросе.

Пример

 // 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;

Хорошее обсуждение того, что вам дает Фьючерс, здесь.

Ответ 3

В NHibernate 3 вы можете использовать QueryOver

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

Вы также можете явно указать свои результаты следующим образом:

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

Ответ 4

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, или все делают то же самое, что и я?

Спасибо

Ответ 5

Как насчет использования Linq для NHibernate, как обсуждалось в этом сообщении в блоге от Ayende?

Пример кода:

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

И вот подробный отчет блога команды NHibernate на Доступ к данным с NHibernate, включая реализацию подкачки.

Ответ 6

Скорее всего, в 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];

Ответ 7

Я предлагаю вам создать определенную структуру для работы с разбиением на страницы. Что-то вроде (я программист на 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. Здесь хорошее обсуждение, чтобы вы могли посмотреть.