Réponses:
ICriteria
a une SetFirstResult(int i)
méthode, qui indique l'index du premier élément que vous souhaitez obtenir (essentiellement la première ligne de données de votre page).
Il a également une SetMaxResults(int i)
méthode, qui indique le nombre de lignes que vous souhaitez obtenir (c'est-à-dire la taille de votre page).
Par exemple, cet objet de critères obtient les 10 premiers résultats de votre grille de données:
criteria.SetFirstResult(0).SetMaxResults(10);
Vous pouvez également profiter de la fonctionnalité Futures de NHibernate pour exécuter la requête afin d'obtenir le nombre total d'enregistrements ainsi que les résultats réels dans une seule requête.
Exemple
// 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>();
Pour obtenir le nombre total d'enregistrements, procédez comme suit:
int iRowCount = rowCount.Value;
Une bonne discussion de ce que les Futures vous offrent est ici .
À partir de NHibernate 3 et supérieur, vous pouvez utiliser QueryOver<T>
:
var pageRecords = nhSession.QueryOver<TEntity>()
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
Vous pouvez également ordonner explicitement vos résultats comme ceci:
var pageRecords = nhSession.QueryOver<TEntity>()
.OrderBy(t => t.AnOrderFieldLikeDate).Desc
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
.Skip(PageNumber * PageSize)
de cette façon, si la taille de la page est de 10, il ne récupérera jamais les 10 premières lignes. Je modifie pour que la formule soit correcte. En supposant que conceptuellement, cela PageNumber
ne devrait pas être égal à 0. Il devrait être au minimum 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); }
}
Lors de la pagination des données, existe-t-il un autre moyen d'obtenir le résultat tapé de MultiCriteria ou tout le monde fait la même chose comme moi?
Merci
Pourquoi ne pas utiliser Linq pour NHibernate comme indiqué dans ce billet de blog d'Ayende?
Exemple de code:
(from c in nwnd.Customers select c.CustomerID)
.Skip(10).Take(10).ToList();
Et voici un article détaillé du blog de l'équipe NHibernate sur l' accès aux données avec NHibernate, y compris la mise en œuvre de la pagination.
Très probablement, dans un GridView, vous souhaiterez afficher une tranche de données plus le nombre total de lignes (rowcount) de la quantité totale de données correspondant à votre requête.
Vous devez utiliser une MultiQuery pour envoyer à la fois la requête Select count (*) et .SetFirstResult (n) .SetMaxResult (m) à votre base de données en un seul appel.
Notez que le résultat sera une liste contenant 2 listes, une pour la tranche de données et une pour le décompte.
Exemple:
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];
Je vous suggère de créer une structure spécifique pour gérer la pagination. Quelque chose comme (je suis un programmeur Java, mais cela devrait être facile à mapper):
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()
}
Je n'ai pas fourni d'implémentation, mais vous pouvez utiliser les méthodes suggérées par @Jon . Voici une bonne discussion à examiner.