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 viable because it would take too much time.

For example, if we load 10,000 products from a catalog, it would be very slow. Furthermore, 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 improves 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 simple pagination implementation.

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

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

Basic pagination implementation

Suppose we want to paginate a list of customers 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();
    }
}
Copied!
  • (page - 1) * recordsPerPage calculates how many records to skip.
  • If page = 1, Skip(0) returns from the first record.

Avoiding Skip for large offsets

In tables with many (millions) of records, Skip() can be slow. This is because Skip must go through all the previous records before omitting them.

To optimize performance in these cases, you can use techniques such as:

  • Indexes on sorting columns: Ensure the columns used in OrderBy are indexed.
  • Key-based pagination: Instead of using Skip, use a Where condition based on the last value from 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();
Copied!