When using SetFirstResult(start)
and SetMaxResults(count)
methods to implement paging I've noticed that the generated query only does a select top count * from some_table
and it does not take the start
parameter into account or at least not at the database level. It seems that if I instruct NHibernate to execute the following query:
var users = session.CreateCriteria<User>()
.SetFirstResult(100)
.SetMaxResults(5)
.List<User>();
105 records will transit between the database server and the application which will take care to strip the first 100 records. With tables containing many rows this could be a problem.
I've verified that with an SQLite database NHibernate takes advantage of the OFFSET
and LIMIT
keywords to filter results at the database level. I am aware that there's no equivalent of the OFFSET
keyword and Oracle's ROWNUM
in SQL Server 2000 but is there any workaround? How about SQL Server 2005/2008?
Nhibernate is smart enough to optimize query. If you select first 10 rows it will use
TOP
statement. If you select not first rows then it will useRowNum
.In sql 2000 there is no
RowNum
function, that's why it is impossible with usual query to select required number of rows. For sql 2000 as I know for such an optimization views were used.In sql 2005/2008 query will select only required rows.
T-SQL, the variant of the SQL language which Microsoft SQL Server uses, does not have a
limit
clause. It has aselect top {...}
modifier which you see NHibernate taking advantage of with SQL Server 2000.With SQL Server 2005, Microsoft introduced the
Row_Number() over (order by {...})
function which can be used as a replacement to thelimit
clause, and you can see NHibernate taking advantage of that with SQL Server 2005/2008.A query for SQLite might look like
while a similar query for SQL Server 2005 might look like
or, using Common Table Expressions, it might look like
There is a way to do it in SQL Server 2000 as well