Risposte:
ICriteria
ha un SetFirstResult(int i)
metodo, che indica l'indice del primo elemento che desideri ottenere (in pratica la prima riga di dati nella tua pagina).
Ha anche un SetMaxResults(int i)
metodo, che indica il numero di righe che desideri ottenere (cioè, la dimensione della tua pagina).
Ad esempio, questo oggetto criteri ottiene i primi 10 risultati della griglia di dati:
criteria.SetFirstResult(0).SetMaxResults(10);
Puoi anche sfruttare la funzionalità Futures in NHibernate per eseguire la query e ottenere il conteggio totale dei record e i risultati effettivi in una singola query.
Esempio
// 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>();
Per ottenere il conteggio totale dei record, procedi come segue:
int iRowCount = rowCount.Value;
Una buona discussione su ciò che i Futures ti danno è qui .
Da NHibernate 3 e versioni successive, puoi utilizzare QueryOver<T>
:
var pageRecords = nhSession.QueryOver<TEntity>()
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
Potresti anche voler ordinare esplicitamente i tuoi risultati in questo modo:
var pageRecords = nhSession.QueryOver<TEntity>()
.OrderBy(t => t.AnOrderFieldLikeDate).Desc
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
.Skip(PageNumber * PageSize)
in questo modo, se la dimensione della pagina è 10, non recupererà mai le prime 10 righe. Sto modificando per rendere la formula corretta. Supponendo che concettualmente, PageNumber
non dovrebbe essere 0. Dovrebbe essere minimo 1.
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); }
}
Quando si impaginano i dati c'è un altro modo per ottenere il risultato digitato da MultiCriteria o tutti fanno lo stesso proprio come me?
Grazie
Che ne dici di usare Linq per NHibernate come discusso in questo post sul blog di Ayende?
Esempio di codice:
(from c in nwnd.Customers select c.CustomerID)
.Skip(10).Take(10).ToList();
Ed ecco un post dettagliato del blog del team di NHibernate sull'accesso ai dati con NHibernate che include l'implementazione del paging.
Molto probabilmente in un GridView vorrai mostrare una porzione di dati più il numero totale di righe (conteggio righe) della quantità totale di dati che corrispondono alla tua query.
È necessario utilizzare un MultiQuery per inviare sia la query Select count (*) che le query .SetFirstResult (n) .SetMaxResult (m) al database in una singola chiamata.
Nota che il risultato sarà un elenco che contiene 2 elenchi, uno per la sezione di dati e uno per il conteggio.
Esempio:
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];
Ti suggerisco di creare una struttura specifica per gestire l'impaginazione. Qualcosa del tipo (sono un programmatore Java, ma dovrebbe essere facile da mappare):
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()
}
Non ho fornito un'implementazione, ma potresti usare i metodi suggeriti da @Jon . Ecco una buona discussione da dare un'occhiata.