3 Stimmen

Subsonic 3.0.0.3 SQL-Paging mit Linq

Ich habe gerade von Subsonic 2.2 ActiveRecord auf 3.0.0.3 aktualisiert. Ich versuche, LINQ zu verwenden, um eine seitenweise Suchabfrage wie diese durchzuführen (mein Objekt/Tabelle heißt "Repository"):

Repository.Find(item => item.DocumentTitle.Contains(searchTerm))
    .OrderBy(i => i.DocumentTitle).Skip((currentPage - 1) * itemsPerPage)
    .Take(itemsPerPage);

Wenn ich mir die von dieser Abfrage mit SQL Server Profiler generierte SQL ansehe, gibt es kein Paging in der SQL, das gesamte Paging wird im Speicher in C# durchgeführt. Die Subsonic-Abfragesprache verfügt über eine nette GetPaged-Prozedur, die richtig funktioniert, aber ich dachte, dass LINQ dies auch tun sollte. Habe ich hier etwas übersehen oder ist dies eine Einschränkung von LINQ?

Ich bin mir bewusst, dass die Repository.GetPaged() Funktion, aber das hat nicht genug Parameter - ich muss eine dynamische Sortierung durchführen, ebenso wie eine Find() .

5voto

Steve Punkte 113

Nach weiteren Tests funktioniert diese Anweisung korrekt:

(from i in dataContext.Repositories 
 where i.DocumentTitle.Contains(searchTerm) 
 orderby i.DateCreated ascending select i)
 .Skip((currentPage - 1) * itemsPerPage).Take(itemsPerPage);

Wenn die obige Linq-Anweisung ausgeführt wird, wird sie ordnungsgemäß in Sql ausgelagert.

Die einzige Schlussfolgerung, die ich ziehen kann, ist, dass bei Verwendung der Syntax für die Methodenverkettung, sobald Sie außerhalb des anfänglichen Lamda-Ausdrucks sind

Repository.Find(item => item.DocumentTitle.Contains(searchTerm))

Der subsonic SQL-Interpreter erzeugt kein SQL mehr für alle Methoden, die am Ende verkettet sind.

.OrderBy(i => i.DocumentTitle).Skip(15).Take(10);

Oder mache ich hier einfach etwas völlig falsch? Hat irgendjemand einen Einblick?

1voto

Sie können GetPaged sortieren, indem Sie "desc" zum Sortierfeld hinzufügen, aber...

Paging sollte funktionieren - ich habe das Paging-SQL vor mir und es wird nicht im Speicher ausgeführt. Wie testen Sie das? Wenn Sie "ToList()" verwenden, wird die Abfrage ausgeführt - sehen Sie sich dann den Profiler an.

0voto

Scott Rickman Punkte 550

Ein bisschen spät, aber ...

Repository.Find()

gibt IList zurück, so dass die Abfrage ausgeführt wird, also wird SQL ohne Paging ausgeführt, dann

.Skip(x).Take(x)

wird im Speicher durchgeführt. Versuchen Sie

Repository.All().Where(expression).Skip(x).Take(x)

die alle IQueryable zurückgeben und die Objekte nicht aufzählen, so dass das Paging in SQL mit der Funktion ROW_NUMBER() durchgeführt wird.

Das einfache Repository von Subsonic 3 generiert jedoch folgendes SQL

exec sp_executesql N'SELECT [t0].[Id], [t0].[IsDeleted], [t0].[Name], [t0].[ParentUuid], [t0].[Uuid]
FROM ( SELECT [t1].[Id], [t1].[IsDeleted], [t1].[Name], [t1].[ParentUuid], ROW_NUMBER() OVER() AS rownum, [t1].[Uuid]
FROM [Sites] AS t1
WHERE (([t1].[ParentUuid] = @p0) AND ([t1].[IsDeleted] = 0))) AS t0
WHERE [t0].[rownum] BETWEEN (20 + 1) AND (20 + 10)',N'@p0 uniqueidentifier',@p0='00000000-0000-0000-0000-000000000000'

was eine Ausnahme auslöst

Unhandled Exception: System.Data.SqlClient.SqlException: The ranking function "ROW_NUMBER" must have an ORDER BY clause.

es scheint also ein Fehler in Subsonic zu sein :-(

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X