Як можна робити пейджінг із NHibernate?


107

Наприклад, я хочу заповнити контроль перегляду сітки на веб-сторінці ASP.NET лише з даними, необхідними для # рядків, що відображаються. Як NHibernate може підтримати це?

Відповіді:


111

ICriteriaмає SetFirstResult(int i)метод, який вказує на індекс першого елемента, який ви бажаєте отримати (в основному це перший рядок даних на вашій сторінці).

Він також має SetMaxResults(int i)метод, який вказує кількість рядків, які ви хочете отримати (тобто розмір вашої сторінки).

Наприклад, цей об’єкт критеріїв отримує перші 10 результатів вашої сітки даних:

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

1
Це майже що синтаксис Linq (для NH) виглядав би як би там не було - Ніцца.
MotoWilliams

13
Важливо зауважити, що вам потрібно буде виконати окрему транзакцію для отримання загальної кількості рядків, щоб зробити пейджер.
Кевін Панг

1
Це виконує запит SELECT TOP у SQL Server. Спробуйте це з SetFirstResult (1) .SetMaxResult (2);
Кріс С

4
У цьому попередньому коментарі використовується NHibernate.Dialect.MsSql2000Dialect не NHibernate.Dialect.MsSql2005Dialect
Chris S

IQuery має ті ж функції, тому його можна використовувати і з HQL.
goku_da_master

87

Ви також можете скористатися функцією 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
Це чудово. Ф'ючерси працюють точно так само, як багатокритерії без синтаксичної складності багатокритерій.
DavGarcia

Після прочитання допису про Futures я не замислююся, чи варто використовувати Future для всіх моїх запитів до бази даних ... Який недолік? :)
hakksor

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 рядків. Я редагую, щоб зробити формулу правильною. Якщо припустити, що концептуально PageNumberце не повинно бути 0. Це повинно бути мінімум 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

Як щодо використання Linq для NHibernate, як обговорювалося в цьому дописі блогу від Ayende?

Зразок коду:

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

Ось детальний пост блогу команди NHibernate про доступ до даних до NHibernate, включаючи впровадження пейджингу.


Зауважте, що linkq до Nhibernate є пакетом внеску та не входить до випуску NHibernate 2.0
Річард

11

Швидше за все, у GridView вам потрібно буде показати фрагмент даних плюс загальну кількість рядків (кількість рядків) від загальної кількості даних, яка відповідає вашому запиту.

Ви повинні використовувати 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

Вам не потрібно визначати 2 критерії, ви можете визначити один і клонувати його. Для клонування критеріїв гібернації ви можете використовувати простий код:

var criteria = ... (your criteria initializations)...;
var countCrit = (ICriteria)criteria.Clone();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.