23

I have a function that retrieves data from database and add it into list. My list is ready and shows the data but i want paging on that list so that it shows limited records per page. but no idea about how to do that.
Here is my code of that data layer function.

 public List<demodto> executereader(List<demodto> Ldemo,SqlCommand cmdshow, string tablename)
    {
         SqlConnection cn;
         try
         {
             cn = this.getconnection();

             cmdshow.Connection = cn;
             cn.Open();

             SqlDataReader rd = cmdshow.ExecuteReader();
             while (rd.Read())
             {
                 demodto dtoobj1 = new demodto();
                 dtoobj1.ID = Convert.ToInt32(rd[0].ToString());
                 dtoobj1.Name = rd[1].ToString();
                 dtoobj1.PhNo = Convert.ToInt32(rd[2].ToString());
                 dtoobj1.Address = rd[3].ToString();
                 dtoobj1.Gender = rd[4].ToString();
                 dtoobj1.Email = rd[5].ToString();
                 dtoobj1.Emptype = rd[6].ToString();

                 Ldemo.Add(dtoobj1);

             }
             cn.Close();
             return Ldemo;
         }
         catch (Exception ex2)
         {
             throw new DataException("error....." + ex2.Message);

         }

    }

And this is for DTO class..

 public class demodto
{
    public Int32 ID{get;set;}
    public string Name{get;set;}
    public Int32 PhNo { get; set; }
    public string Address{get;set;}
    public string Gender { get; set; }
    public string Email { get; set; }
    public string Emptype { get; set; }
 }

please help me. Thanks.

vidhi
  • 411
  • 1
  • 6
  • 19

7 Answers7

53

You can page a list with LINQ, like this:

IList<demodto> GetPage(IList<demodto> list, int page, int pageSize) {
    return list.Skip(page*pageSize).Take(pageSize).ToList();
}

For example, suppose each page has 50 records. To get a third page, call

IList<demodto> thirdPage = GetPage(dataList, 3, 50);

Note, however, that applying paging to data in memory makes very little sense: the idea behind paging is to cut down on the time it takes to retrieve your data from the database, and to save some memory by keeping only a single page, which is not going to happen in your case, because all data is retrieved at once.

In order to make paging worth the effort, you need to move it into the database. Change your method to accept page size and number, and use them to change the SQL to retrieve the list for a single page. Don't forget to force ordering on your sql read, otherwise the same data might appear on different pages. Your SQL needs to be modified to support pagination. This is done differently depending on your database. MS SQL Server solution is described in this answer.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 3
    Shouldn't it be `return list.Skip(page - 1 * pageSize).Take(pageSize).ToList();` ? – Saket Kumar Feb 02 '15 at 14:25
  • 2
    @Saket It depends on whether you consider `page` one-based or zero-based. I prefer zero-based numbering. – Sergey Kalinichenko Feb 02 '15 at 14:40
  • @dasblinkenlight do you have any idea how to know the total page number of the given collection length via LINQ? – Shift 'n Tab Aug 16 '16 at 03:40
  • @Roel, i'm a little late to the party but you could use: `int result = Math.DivRem(int a, int b, out new int remainder);` If remainder is greater than 0 add one to the result (the quotient) and that is your total page count. [Math.DivRem()](https://learn.microsoft.com/en-us/dotnet/api/system.math.divrem?view=netframework-4.8) – Bryan Halterman May 15 '19 at 17:53
2
int pagesize = 1000;
int countitens = list1.Count();
int pagecount = countitens % pagesize <= 0 ? countitens / pagesize : (countitens / pagesize) + 1; // for example 10001 itens and page size of 1000 retusn 2 pages
for (int page = 0; page < pagecount; page++)
{
    var itens = list1.Skip(page * pagesize).Take(pagesize).ToList();
}

Or just

var itens = list1.Skip(page-1 * pagesize).Take(pagesize).ToList(); // page-1 if value of page start with 1
0
_context.skip(5).take(10)

Try to use this one. Better explanation in this question Paging with LINQ for objects

Community
  • 1
  • 1
BorHunter
  • 893
  • 3
  • 18
  • 44
0

Skip and Take extension methods fits your needs.I don't know how is your page structure but you can use a simple for loop to get values like this:

int recordPerPage = 20;
for(int i=0; i<pageCount; i++)
{ 
   var values = list.Skip(recordPerPage*i).Take(recordPerPage).ToList();
   // add values to the page or display whatever..
}
Selman Genç
  • 100,147
  • 13
  • 119
  • 184
0

In new versions of SQL Server you can use the ROWNUMBER Function

rowStart    = ((Page - 1) * PageSize) + 1
rowEnd      = Page * PageSize

SELECT * From (SELECT ROW_NUMBER() {0} As RowNum, * FROM table WHERE condition) AS RowConstrainedResult Where RowNum >= rowStart And RowNum <= rowEnd Order By RowNum

This then makes the whole thing a lot quicker as you are not bringing back the whole data-set, just those records on the page you want

Paul S Chapman
  • 832
  • 10
  • 37
0

You can iterate while checking that the list is fully processed:

using System;
using System.Linq;

var list = new bool[21];
var batchSize = 10;

var count = list.Length;
var remain = count;
while(remain > 0) {
    var batch = list.Skip(count - remain).Take(batchSize);
    Console.WriteLine($"remain: {remain}\t.Skip({count - remain}).Take({batchSize})\tbatchCount: {batch.Count()}");
    remain -= batchSize;
}

Output:

remain: 21    .Skip(0).Take(10)    batchCount: 10
remain: 11    .Skip(10).Take(10)   batchCount: 10
remain: 1     .Skip(20).Take(10)   batchCount: 1
Himura
  • 1,686
  • 1
  • 13
  • 19
0

Starting from .NET 6 you can write this:

list.Chunk(pageSize).ElementAt(page); // page starts from 0
iikuzmychov
  • 129
  • 1
  • 9