NHibernate Paging mit SQL Server
-
22-07-2019 - |
Frage
Wenn SetFirstResult(start)
und SetMaxResults(count)
Methoden Paging zu implementieren ich bemerkt habe, dass die erzeugte Abfrage nur eine select top count * from some_table
tut und es nimmt nicht die start
Parameter berücksichtigt oder zumindest nicht auf Datenbankebene. Es scheint, dass, wenn ich anweisen NHibernate die folgende Abfrage ausführen:
var users = session.CreateCriteria<User>()
.SetFirstResult(100)
.SetMaxResults(5)
.List<User>();
105 Datensätze Transit zwischen dem Datenbankserver und die Anwendung, die darauf achten, werden die ersten 100 Datensätze strippen. Mit Tabellen viele Zeilen enthalten, könnte dies ein Problem sein.
Ich habe mit einem SQLite Datenbank nimmt NHibernate Vorteil der OFFSET
und LIMIT
Schlüsselwort Nachweis erbracht, dass die Ergebnisse filtern auf Datenbankebene. Ich bin mir bewusst, dass es kein Äquivalent des OFFSET
Schlüsselwort und Oracle ROWNUM
in SQL Server 2000 aber gibt es eine Abhilfe? Wie wäre es SQL Server 2005/2008?
Lösung
T-SQL, die Variante der SQL-Sprache, die Microsoft SQL Server verwendet, hat keine limit
Klausel. Es hat einen select top {...}
Modifikator, die Sie NHibernate sehen Vorteil mit SQL Server 2000 unter.
Mit SQL Server 2005 hat Microsoft die Row_Number() over (order by {...})
Funktion, die als Ersatz für die limit
Klausel verwendet werden kann, und Sie können NHibernate sehen Vorteil, dass mit SQL Server 2005/2008 nehmen.
Eine Abfrage für SQLite könnte so aussehen
select c.[ID], c.[Name]
from [Codes] c
where c.[Key] = 'abcdef'
order by c.[Order]
limit 20 offset 40
, während eine ähnliche Abfrage für SQL Server 2005 aussehen könnte
select c.[ID], c.[Name]
from (
select c.[ID], c.[Name], c.[Order]
, [!RowNum] = Row_Number() over (order by c.[Order])
from [Codes] c
where c.[Key] = 'abcdef'
) c
where c.[!RowNum] > 40 and c.[!RowNum] <= 60
order by c.[Order]
oder unter Verwendung von Common Table Expressions, könnte es aussehen
with
[Source] as (
select c.[ID], c.[Name], c.[Order]
, [!RowNum] = Row_Number() over (order by c.[Order])
from [Codes] c
where c.[Key] = 'abcdef'
)
select c.[ID], c.[Name]
from [Source] c
where c.[!RowNum] > 40 and c.[!RowNum] <= 60
order by c.[Order]
Es gibt einen Weg, um es in SQL Server 2000 als auch
zu tunselect c.[ID], c.[Name]
from (
select top 20 c.[ID], c.[Name], c.[Order]
from (
select top 60 c.[ID], c.[Name], c.[Order]
from [Codes] c
where c.[Key] = 'abcdef'
order by c.[Order]
) c
order by c.[Order] desc
) c
order by c.[Order]
Andere Tipps
Nhibernate ist intelligent genug, um Abfrage zu optimieren. Wenn Sie die ersten 10 Zeilen auswählen wird es TOP
Anweisung verwenden. Wenn Sie nicht erste Zeilen auswählen, dann wird es RowNum
verwenden.
In SQL 2000 gibt es keine RowNum
Funktion, das ist, warum es nicht möglich, mit den üblichen Abfrage erforderliche Anzahl von Zeilen auszuwählen. Für SQL 2000, als ich für eine solche Optimierung Ansichten wurden verwendet, um wissen.
In SQL 2005/2008 Abfrage wählt nur Zeilen erforderlich.