Odpowiedzi:
ICriteria
ma SetFirstResult(int i)
metodę, która wskazuje indeks pierwszego elementu, który chcesz uzyskać (w zasadzie pierwszy wiersz danych na twojej stronie).
Posiada również SetMaxResults(int i)
metodę, która wskazuje liczbę wierszy, które chcesz uzyskać (tj. Rozmiar strony).
Na przykład ten obiekt kryteriów pobiera pierwszych 10 wyników siatki danych:
criteria.SetFirstResult(0).SetMaxResults(10);
Możesz również skorzystać z funkcji Futures w NHibernate, aby wykonać zapytanie w celu uzyskania całkowitej liczby rekordów, a także rzeczywistych wyników w pojedynczym zapytaniu.
Przykład
// 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>();
Aby uzyskać całkowitą liczbę rekordów, wykonaj następujące czynności:
int iRowCount = rowCount.Value;
Dobrym dyskusja co Futures dać to tutaj .
Od NHibernate 3 i nowszych możesz użyć QueryOver<T>
:
var pageRecords = nhSession.QueryOver<TEntity>()
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
Możesz również jawnie uporządkować wyniki w następujący sposób:
var pageRecords = nhSession.QueryOver<TEntity>()
.OrderBy(t => t.AnOrderFieldLikeDate).Desc
.Skip((PageNumber - 1) * PageSize)
.Take(PageSize)
.List();
.Skip(PageNumber * PageSize)
w ten sposób, jeśli rozmiar strony to 10, nigdy nie pobierze pierwszych 10 wierszy. Edytuję, aby poprawić formułę. Zakładając, że koncepcyjnie PageNumber
nie powinno być 0. Powinno być 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); }
}
Czy podczas stronicowania danych istnieje inny sposób uzyskania wpisanego wyniku z MultiCriteria, czy też wszyscy robią to samo, tak jak ja?
Dzięki
Co powiesz na użycie Linq do NHibernate, jak omówiono w tym poście na blogu Ayende?
Przykład kodu:
(from c in nwnd.Customers select c.CustomerID)
.Skip(10).Take(10).ToList();
A oto szczegółowy post blogu zespołu NHibernate na temat dostępu do danych z NHibernate, w tym implementacji stronicowania.
Najprawdopodobniej w GridView będziesz chciał wyświetlić wycinek danych oraz łączną liczbę wierszy (rowcount) z łącznej ilości danych, które pasują do zapytania.
Powinieneś użyć MultiQuery, aby wysłać zarówno zapytanie Select count (*), jak i .SetFirstResult (n) .SetMaxResult (m) do bazy danych w jednym wywołaniu.
Zwróć uwagę, że wynikiem będzie lista zawierająca 2 listy, jedną dla wycinka danych i jedną dla liczby.
Przykład:
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];
Proponuję stworzyć specjalną strukturę zajmującą się paginacją. Coś takiego (jestem programistą Java, ale to powinno być łatwe do zmapowania):
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()
}
Nie dostarczyłem implementacji, ale możesz użyć metod sugerowanych przez @Jon . Oto dobra dyskusja do obejrzenia.