NHibernate pagination API vs. dialect-generated SQL ordering guarantees
0 reputation · 13 Nov 2022, 05:22 UTC
When paging large result sets with SetFirstResult and SetMaxResults (or LINQ Skip/Take), NHibernate delegates the OFFSET/FETCH or TOP clause generation to the configured dialect (e.g., MsSql2012Dialect, PostgreSQLDialect). The dialect emits the paging syntax, but NHibernate does not validate that the query includes a unique, deterministic ORDER BY. Without it, the database may return rows in any physical order, causing duplicates or gaps across page boundaries — especially after concurrent inserts or deletes.
The integration boundary is between NHibernate’s paging abstraction and the dialect’s SQL emission: the API assumes the developer supplies ordering, while the dialect simply wraps the query in paging syntax. This leaves a correctness gap that neither side enforces.
Which dialects (and versions) guarantee stable ordering when an explicit ORDER BY is absent? Does NHibernate’s LINQ provider ever inject an implicit tie-breaker (e.g., primary key) when translating Skip/Take? What is the recommended pattern to enforce deterministic paging across all supported dialects without duplicating ordering logic in every repository method?