Bagaimana Anda bisa melakukan paging dengan NHibernate?

107

Misalnya, saya ingin mengisi kontrol gridview di halaman web ASP.NET hanya dengan data yang diperlukan untuk # baris yang ditampilkan. Bagaimana NHibernate dapat mendukung ini?

sinar
sumber

Jawaban:

111

ICriteriamemiliki SetFirstResult(int i)metode, yang menunjukkan indeks item pertama yang ingin Anda dapatkan (pada dasarnya baris data pertama di halaman Anda).

Ini juga memiliki SetMaxResults(int i)metode, yang menunjukkan jumlah baris yang ingin Anda dapatkan (yaitu, ukuran halaman Anda).

Misalnya, objek kriteria ini mendapatkan 10 hasil pertama dari kisi data Anda:

criteria.SetFirstResult(0).SetMaxResults(10);
Jon Limjap
sumber
1
Seperti inilah sintaks Linq (ke NH) akan terlihat - Bagus.
MotoWilliams
13
Penting untuk dicatat bahwa Anda perlu menjalankan transaksi terpisah untuk mengambil jumlah baris total untuk membuat pager Anda.
Kevin Pang
1
Ini melakukan query SELECT TOP di SQL Server. Cobalah dengan SetFirstResult (1) .SetMaxResult (2);
Chris S
4
Itu komentar sebelumnya menggunakan NHibernate.Dialect.MsSql2000Dialect bukan NHibernate.Dialect.MsSql2005Dialect
Chris S
IQuery memiliki fungsi yang sama, sehingga dapat digunakan dengan HQL juga.
goku_da_master
87

Anda juga dapat memanfaatkan fitur Futures di NHibernate untuk mengeksekusi kueri untuk mendapatkan jumlah catatan total serta hasil aktual dalam satu kueri.

Contoh

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

Untuk mendapatkan jumlah catatan total, Anda melakukan hal berikut:

int iRowCount = rowCount.Value;

Diskusi yang bagus tentang apa yang Futures berikan untuk Anda ada di sini .

Jeremy D
sumber
3
Ini bagus. Futures bekerja persis seperti multikriteria tanpa kompleksitas sintaksis dari multikriteria.
DavGarcia
Setelah membaca postingan tentang Futures, saya bertanya-tanya apakah saya harus menggunakan Future untuk semua kueri database saya ... Apa kekurangannya? :)
hakksor
46

Dari NHibernate 3 ke atas, Anda dapat menggunakan QueryOver<T>:

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

Anda mungkin juga ingin mengurutkan hasil secara eksplisit seperti ini:

var pageRecords = nhSession.QueryOver<TEntity>()
            .OrderBy(t => t.AnOrderFieldLikeDate).Desc
            .Skip((PageNumber - 1) * PageSize)
            .Take(PageSize)
            .List();
Leandro de los Santos
sumber
.Skip(PageNumber * PageSize)dengan cara ini, jika ukuran halaman 10, 10 baris pertama tidak akan pernah diambil. Saya mengedit untuk membuat rumusnya benar. Dengan asumsi bahwa secara konseptual, PageNumberseharusnya tidak 0. Ini harus minimum 1.
Amit Joshi
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); }
      }

Ketika paging data apakah ada cara lain untuk mendapatkan hasil yang diketik dari MultiKriteria atau semua orang melakukan hal yang sama seperti saya?

Terima kasih

Barbaros Alp
sumber
23

Bagaimana jika menggunakan Linq ke NHibernate seperti yang dibahas dalam posting blog ini oleh Ayende?

Contoh Kode:

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

Dan berikut adalah posting rinci oleh blog tim NHibernate tentang Akses Data Dengan NHibernate termasuk menerapkan paging.

NotMyself
sumber
Catatan linq ke Nhibernate ada dalam paket kontrib dan tidak termasuk dalam rilis NHibernate 2.0
Richard
11

Kemungkinan besar dalam GridView Anda akan ingin menampilkan sepotong data ditambah jumlah baris (jumlah baris) dari jumlah total data yang cocok dengan kueri Anda.

Anda harus menggunakan MultiQuery untuk mengirim kueri Select count (*) dan .SetFirstResult (n) .SetMaxResult (m) ke database Anda dalam satu panggilan.

Perhatikan hasilnya akan menjadi daftar yang menampung 2 daftar, satu untuk potongan data dan satu untuk hitungan.

Contoh:

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];
zadam
sumber
6

Saya menyarankan agar Anda membuat struktur khusus untuk menangani penomoran halaman. Sesuatu seperti (Saya seorang programmer Java, tetapi itu seharusnya mudah dipetakan):

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

}

Saya tidak menyediakan implementasi, tetapi Anda dapat menggunakan metode yang disarankan oleh @Jon . Berikut adalah pembahasan yang bagus untuk Anda lihat.

Marcio Aguiar
sumber
0

Anda tidak perlu menentukan 2 kriteria, Anda dapat menentukan satu dan mengkloningnya. Untuk mengkloning kriteria nHibernate, Anda dapat menggunakan kode sederhana:

var criteria = ... (your criteria initializations)...;
var countCrit = (ICriteria)criteria.Clone();
Marcin
sumber