I want to page over some records but the Take()
extension from LINQ
isn\'t returning the result which I expected.
public IQueryable<
The Take
method returns the first N records (N being the parameter) or all of the records if the total is less than N. To implement paging use it in conjunction with Skip
, specifying how many records to skip before taking the next page of results. You may also want to supply some total ordering to ensure that the query returns results in the same order each time.
Note: I've assumed zero-based paging.
private const int _pageSize = 20;
public IQueryable<Person> GetPersonBetweenDates(DateTime start, DateTime end, int? page)
{
return dbcontext.Persons
.Where(x => x.RegisterDate >= start && x.RegisterDate <= end)
.OrderBy(x => x.LastName)
.ThenBy(x => x.FirstName)
.ThenBy(x => x.Id) // using unique id to force consistent total order
.Skip((page ?? 0) * _pageSize)
.Take(_pageSize);
}
.Take
returns the specified number of results on a query, and if it is the same query it will often return the same results. To resolve this, you might use a combination of .Skip
and .Take
, changing the number you are Skip
ping and Take
ing each time.
private int counter = 0;
public IQueryable<Person> GetPersonBetweenDates(DateTime start, DateTime end)
{
var results = dbcontext.Persons.Where(x => x.RegisterDate >= start && x.RegisterDate <= end).Skip(counter).Take(20);
counter += 20;
return results;
}
Keep in mind that you will be able to call this continuously, even after there are no more records.
Alternatively, you could cache the query (if you aren't reinstantiating the class on each use):
private IQueryable<Person> qry = dbcontext.Persons.Where(x => x.RegisterDate >= start && x.RegisterDate <= end);
public IQueryable<Person> GetPersonBetweenDates(DateTime start, DateTime end)
{
qry = qry.Skip(20);
return qry.Take(20);
}
Nevertheless, both of these snippets may have other issues -- see tvanfosson's comments and answer.