Respostas:
ICriteria
tem um SetFirstResult(int i)
método, que indica o índice do primeiro item que você deseja obter (basicamente, a primeira linha de dados em sua página).
Ele também possui um SetMaxResults(int i)
método, que indica o número de linhas que você deseja obter (ou seja, o tamanho da página).
Por exemplo, este objeto de critérios obtém os primeiros 10 resultados de sua grade de dados:
criteria.SetFirstResult(0).SetMaxResults(10);
Você também pode tirar proveito do recurso Futures no NHibernate para executar a consulta para obter a contagem total de registros, bem como os resultados reais em uma única consulta.
Exemplo
// 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 obter a contagem total de registros, você faz o seguinte:
int iRowCount = rowCount.Value;
Uma boa discussão sobre o que o Futures oferece a você está aqui .
Do NHibernate 3 e superior, você pode usar QueryOver<T>
:
var pageRecords = nhSession.QueryOver<TEntity>()
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
Você também pode querer ordenar explicitamente seus resultados desta forma:
var pageRecords = nhSession.QueryOver<TEntity>()
.OrderBy(t => t.AnOrderFieldLikeDate).Desc
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
.Skip(PageNumber * PageSize)
dessa forma, se o tamanho da página for 10, ele nunca recuperará as primeiras 10 linhas. Estou editando para tornar a fórmula correta. Supondo que conceitualmente, PageNumber
não deve ser 0. Deve 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); }
}
Quando dados de paginação, há outra maneira de obter resultados digitados de MultiCriteria ou todos fazem o mesmo como eu?
obrigado
Que tal usar o Linq para NHibernate, conforme discutido neste post de blog de Ayende?
Amostra de código:
(from c in nwnd.Customers select c.CustomerID)
.Skip(10).Take(10).ToList();
E aqui está uma postagem detalhada do blog da equipe do NHibernate sobre Acesso a dados com NHibernate, incluindo a implementação de paginação.
Muito provavelmente, em um GridView, você desejará mostrar uma fatia de dados mais o número total de linhas (número de linhas) da quantidade total de dados que correspondem à sua consulta.
Você deve usar uma MultiQuery para enviar a consulta Select count (*) e as consultas .SetFirstResult (n) .SetMaxResult (m) ao seu banco de dados em uma única chamada.
Observe que o resultado será uma lista que contém 2 listas, uma para a fatia de dados e outra para a contagem.
Exemplo:
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];
Eu sugiro que você crie uma estrutura específica para lidar com a paginação. Algo como (sou um programador Java, mas deve 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()
}
Não forneci uma implementação, mas você pode usar os métodos sugeridos por @Jon . Aqui está uma boa discussão para você dar uma olhada.