BuildingBlocks.Pagination.EntityFrameworkCore 1.1.0
·
32 commits
to main
since this release
Summary
Index-friendlier keyset pagination: PostgreSQL multi-column row comparison, ORDER BY NULLS FIRST/LAST end-to-end where supported, optional matching index null-sort metadata, and aligned Dapper SQL generation.
NuGet
BuildingBlocks.Pagination.EntityFrameworkCore 1.1.0
dotnet add package BuildingBlocks.Pagination.EntityFrameworkCore --version 1.1.0Features added
EF Core (packaged)
- Npgsql row-comparison seek for uniform non-nullable multi-column keys of any width (
(a, b, …) > …via soft-resolvedEF.Functions.GreaterThan/LessThan).- 2–8 columns:
ValueTuple.Create - 9+: nested
ValueTupleTRest - Mixed ASC/DESC,
stringslots, Sqlite, and SQL Server keep the expanded OR seek
- 2–8 columns:
AddBuildingBlocksPagination()+UseBuildingBlocksPagination()—DbCommandInterceptorappendsNULLS FIRST/LASTon Npgsql/Sqlite at execute time- Placement encoded in query tag
BuildingBlocks.Pagination:First|Last(inverted on backward walks) - Not
AsyncLocal; Add-without-Use stays 1.0-compatible (seek-onlyNullOrder) ToQueryString()does not run interceptors — assert executed SQL for NULLS
- Placement encoded in query tag
HasKeysetIndex(sortKey, NullOrder)— soft call to NpgsqlHasNullSortOrderso index NULLS can matchORDER BY … NULLS …- One-argument
HasKeysetIndex(sortKey)does not write null-sort metadata - Npgsql omits
NULLSfromCREATE INDEXwhen it matches the column ASC/DESC default
- One-argument
- EF seek null comparisons for reference/
stringslots align with true NULLS FIRST/LAST semantics (fixes end-to-end null ordering with the interceptor)
IR (bundled in the same nupkg)
NullOrdercontract documented as seek and ORDER BY null placement where supported (was seek-predicate only in 1.0)SeekOpshelpers for tuple eligibility / non-null slots used by EF and Dapper
Dapper (in-repo project, not a separate NuGet)
ORDER BY … NULLS FIRST/LASTon PostgreSQL and Sqlite fromPaginationOptions.Nulls(inverted on backward walks)- SQL Server still omits
NULLS - Existing Postgres tuple SQL for uniform directions remains; coverage extended for wider keys (3 / 4 / 9 columns)
Lab (FeatureFusion)
NameThenPriceproduct sort (3-column keyset: Name, Price, Id)- Registers
AddBuildingBlocksPagination+UseBuildingBlocksPagination - Matching indexes / migration for the new sort
Tests / CI
- EF Postgres Testcontainers: 2-, 3-, 4-, 9-column tuple SQL shape; string/mixed stay OR; NULLS via interceptor
- Model-only
HasKeysetIndex→CREATE INDEXcontains non-defaultNULLS FIRST - Dapper: NULLS on PG/Sqlite, no NULLS on SQL Server; multi-column tuple SQL
pagination.yml:PAGINATION_POSTGRES_REQUIRED— skipped Postgres tests fail CI
Host checklist
- Upgrade to 1.1.0 (drop-in for existing
ToCursorPageAsync/ OR seek). - For EF
ORDER BY … NULLS …: call bothservices.AddBuildingBlocksPagination()andoptions.UseBuildingBlocksPagination(). - Optionally
HasKeysetIndex(key, NullOrder.First|Last)when NULLS is not the ASC/DESC default. - Host must already reference Npgsql.EntityFrameworkCore.PostgreSQL for tuple seek / index null-sort (no hard PackageReference in the nupkg).
Unchanged / non-goals in 1.1.0
- Nullable value-type sort slots (
int?,DateTime?, …) still throwNullableSortUnsupported - SQL Server still does not emit
NULLSon ORDER BY - Dapper remains an in-repo project (not packed)
Docs
What's Changed
- feat(pagination): ship 1.1.0 by @Maxofpower in #21
Full Changelog: idempotency-v1.0.0...pagination-v1.1.0