entity-framework-paginacion-skip-take

Pagination in Entity Framework using `Skip` and `Take`

  • 3 min

In Entity Framework, we can implement pagination easily using the Skip() and Take() methods.

In applications that handle large volumes of data, retrieving all records from a database in a single query may not be feasible because it would take too much time.

For example, if we load 10,000 products from a catalog, it would be very slow. Moreover, the user does not need (nor can they) see 10,000 products at once.

Pagination allows us to split the results into manageable chunks. This enhances the user experience and also reduces resource consumption.

What are Skip and Take?

These methods belong to LINQ and are used to:

  • Skip(n): Skips the first n elements of a query.
  • Take(m): Selects the next m elements after skipping.

Together, they allow for very easy pagination.

For example, if we have a Products table with 100 records and want to display 10 per page, the second page can be obtained with:

var page2 = dbContext.Products
    .OrderBy(p => c.Id) 
    .Skip(10)  // Skips the first 10
    .Take(10)  // Takes the next 10
    .ToList();

Basic pagination implementation

Let’s suppose we want to paginate a list of clients in a web application. The code would be:

public List<Client> GetPaginatedClients(int page, int recordsPerPage)
{
    using (var context = new AppDbContext())
    {
        return context.Clients
            .OrderBy(c => c.Name)  // Important to sort!
            .Skip((page - 1) * recordsPerPage)
            .Take(recordsPerPage)
            .ToList();
    }
}
  • (page - 1) * recordsPerPage calculates how many records to skip.
  • If page = 1, Skip(0) returns from the first record.

Avoid Skip on large offsets

In tables with many (millions) of records, Skip() can be slow. This is because Skip has to traverse all previous records before skipping them.

To optimize performance in these cases, techniques such as:

  • Indexes on sorting columns: Ensure that the columns used in OrderBy are indexed.
  • Key-based pagination: Instead of using Skip, use a Where condition based on the last value of the previous page.

For example, if we are paginating products by their ID:

int lastId = 10; // Last ID from the previous page
int pageSize = 10;

var products = context.Products
    .Where(p => p.Id > lastId)
    .OrderBy(p => p.Id)
    .Take(pageSize)
    .ToList();