Cursor-based seek/keyset pagination for Entity Framework Core - in a singe line.
$ dotnet add package CursedQueryable.EntityFrameworkCoreCursedQueryable is a library that aims to implement cursor-based keyset pagination (aka seek pagination) for IQueryable
with as close to zero boilerplate code as possible. This is achieved via examining the underlying expression tree for
any IQueryable instance and rewriting it as needed prior to any database calls being made.
This repository contains the implementation for using CursedQueryable with Entity Framework Core, and is the primary
expected use case for CursedQueryable. If you're wanting to integrate with a different IQueryable provider than
EFCore, you should grab the core library from the CursedQueryable repository instead.
CursedQueryable.EntityFrameworkCore is compatible with Entity Framework Core versions 5 and above, and should work with any provider that plugs into it. It has been verified as working against the following specific providers:
| Provider | Databases | Notes |
|---|---|---|
| Pomelo.EntityFrameworkCore.MySql | MariaDB, MySQL | |
| MySql.EntityFrameworkCore | MySql | ⚠ EFCore 5 only: primary key(s) and ordering columns cannot be of type System.Guid. |
| Oracle.EntityFrameworkCore | Oracle | Ensure NullBehaviour.LargerThanNonNullable is set. |
| Npgsql.EntityFrameworkCore.PostgreSQL | Postgres | Ensure NullBehaviour.LargerThanNonNullable is set. |
| Microsoft.EntityFrameworkCore.SqlServer | SQL Server |
Reference the CursedQueryable.EntityFrameworkCore package, make sure it's configured correctly, then
just call the CursedQueryable extension methods .ToPage()/.ToPageAsync() instead of .ToList()/.ToListAsync():
using CursedQueryable.Extensions;
public async Task<Page<Cat>> GetPageOfCats(string? cursor)
{
return await dbContext
.Cats
.Take(10)
.ToPageAsync(cursor);
}
// This will get an initial page of (up to) 10 cats
var pageOfCats = await GetPageOfCats(null);
Additional documentation is available in the CursedQueryable repository.