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?

War es hilfreich?

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 tun
select 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.


Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top