Respuestas:
ICriteria
tiene un SetFirstResult(int i)
método, que indica el índice del primer elemento que desea obtener (básicamente la primera fila de datos en su página).
También tiene un SetMaxResults(int i)
método, que indica el número de filas que desea obtener (es decir, el tamaño de su página).
Por ejemplo, este objeto de criterios obtiene los primeros 10 resultados de su cuadrícula de datos:
criteria.SetFirstResult(0).SetMaxResults(10);
También puede aprovechar la función Futuros en NHibernate para ejecutar la consulta y obtener el recuento total de registros, así como los resultados reales en una sola consulta.
Ejemplo
// 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>();
Para obtener el recuento total de registros, haga lo siguiente:
int iRowCount = rowCount.Value;
Aquí encontrará una buena discusión sobre lo que le ofrecen los futuros .
Desde NHibernate 3 y superior, puede usar QueryOver<T>
:
var pageRecords = nhSession.QueryOver<TEntity>()
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
Es posible que también desee ordenar explícitamente sus resultados de esta manera:
var pageRecords = nhSession.QueryOver<TEntity>()
.OrderBy(t => t.AnOrderFieldLikeDate).Desc
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
.Skip(PageNumber * PageSize)
de esta manera, si el tamaño de la página es 10, nunca recuperará las primeras 10 filas. Estoy editando para que la fórmula sea correcta. Suponiendo que conceptualmente, PageNumber
no debería ser 0. Debería ser mínimo 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); }
}
Cuando los datos de paginación, ¿hay otra forma de obtener un resultado escrito de MultiCriteria o todos hacen lo mismo como yo?
Gracias
¿Qué tal usar Linq para NHibernate como se explica en esta publicación de blog de Ayende?
Ejemplo de código:
(from c in nwnd.Customers select c.CustomerID)
.Skip(10).Take(10).ToList();
Y aquí hay una publicación detallada del blog del equipo de NHibernate sobre Acceso a datos con NHibernate, incluida la implementación de paginación.
Lo más probable es que en un GridView desee mostrar una porción de datos más el número total de filas (recuento de filas) de la cantidad total de datos que coinciden con su consulta.
Debe usar una MultiQuery para enviar tanto la consulta Select count (*) como las consultas .SetFirstResult (n) .SetMaxResult (m) a su base de datos en una sola llamada.
Tenga en cuenta que el resultado será una lista que contiene 2 listas, una para el segmento de datos y otra para el recuento.
Ejemplo:
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];
Sugiero que cree una estructura específica para lidiar con la paginación. Algo como (soy un programador de Java, pero debería ser fácil de mapear):
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()
}
No proporcioné una implementación, pero podrías usar los métodos sugeridos por @Jon . Aquí tienes una buena discusión para que la eches un vistazo.