2013-07-22 9 views
9

Meine Tabelle besteht aus drei Spalten (Sno, Name, Alter). I diese Tabelle mit zusätzlichen Spalt aus der Datenbank am Abrufen (Zeilennummer) und I verwendet, um den folgenden Code:Wie übersetze ich eine Abfrage, die ROW_NUMBER() in linq verwendet?

select * from (
    select ROW_NUMBER() over (order by SNo asc)as rowindex,SNo,Name,Age 
    from tblExample) 
    as example where rowindex between ((pageindex*10)+1) and ((pageindex+1)*10) 

Hinweis, Pageindex ist die Variable, die einen ganzzahlige Wert annimmt, die durch den Benutzer übergeben wird.

Meine Datenbank ist Sql Server 2008. Ich möchte die gleiche Abfrage mit Linq schreiben. Wie mache ich das?

+0

LINQ to SQL? LINQ zu EF? –

+0

Ohne die gesamte Menge zu ziehen und möglicherweise eine Variable oder den überladenen '.Select'-Operator zu verwenden, glaube ich nicht, dass es einen LINQ-Befehl gibt, der diese Abfrage übersetzt. –

Antwort

7

Sie können Abfrage schreiben als Beow

var index=1; 
var pageIndex=1; 
var pageSize = 10; 
data.Select(x => new 
{ 
    RowIndex = index++, 
    Sno = x.Sno, 
    Name = x.Name, 
    Age = x.Age 
}).OrderBy(x => x.Name) 
.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList(); 
+3

'Ein Ausdrucksbaum darf keinen Zuweisungsoperator enthalten 'Wie genau funktioniert das für Sie (ohne die Liste zuerst lokal zu cachen)? –

+0

@Simon Belanger: Seine Anforderung ist es, mithilfe von linq dynamisch in der Grid-Ansicht zu paginieren. In diesem Fall funktioniert das obige Szenario perfekt. Versuchen Sie Ihr Selbst es funktioniert perfekt für mich – sree

7

keine direkte Übersetzung, aber da nur Ihre Zeilennummer erscheint Blätter verwendet werden, versuchen:

db.tblExample 
    .OrderBy(t => t.SNo) 
    .Select((t,i) => new {rowindex = i+1, t.SNo, t.Name, t.Age }) 
    .Skip(pageIndex * 10) 
    .Take(10); 

EDIT

Wenn Select((t,i) => ...) nicht Sie versuchen können, funktioniert die Synthese die Indexnummer, indem sie nach der Befeuchtung der Abfrage hinzugefügt wird:

db.tblExample 
    .OrderBy(t => t.SNo) 
    .Skip(pageIndex * 10) 
    .Take(10) 
    .AsEnumerable(); 
    .Select((t,i) => new {rowindex = (pageIndex*10)+i+1, t.SNo, t.Name, t.Age }) 

Sie sollten mit gleichwertig SQL anders als die Tatsache, dass das rowindex Feld wird nicht von der SQL-Abfrage zurückgegeben werden, sondern wird stattdessen von der Mitgliedsauswahl Ausdruck hinzugefügt.

+0

Die Überladung '.Select (Func )' kann nicht verwendet werden, um eine Abfrage zu erstellen ('Nicht unterstützte Überladung für Abfrageoperator 'Select'.), Die Ergebnisse müssen zuerst lokal gespeichert werden. Wenn dies ein DB-Kontext ist, müssen Sie zuerst '.ToList()' (oder Äquiv.) Aufrufen. –

+1

Ich rate davon ab, '.ToList()' vor dem '.Select() 'aufzurufen, wie es hier geschrieben ist; das würde alles in den Speicher laden, was den Zweck des Paging zunichte macht.Stattdessen tun Sie zuerst '.Skip()' und '.Take()', dann '.ToList()', dann '.Select()' das Ergebnis in Ihr Ausgabeformat. – anaximander

+0

@anaximander: es muss in den Speicher geladen werden, um die Überlast zu verwenden; Darauf bezog ich mich mit 'Nicht unterstützte Überladung ...'. –

0

Best-Case-Szenario (wenn Sie Notwendigkeit die Metadaten):

var rows = db.tblExample   // database context 
      .OrderBy(x => x.SNo) // set an orderby 
      .AsEnumerable()  // force query execution (now we have local dataset) 
      .Select(x => new 
      { 
       rowindex = i, 
       SNo = x.Sno, 
       Name = x.Name, 
       Age = x.Age 
      });     // now you have your original query 

Der einzige Nachteil hier ist, dass der gesamte Datensatz sein muss gezogen, um diese Metadaten zu erhalten. Wenn Sie jedoch .Skip & .Take verwenden, übersetzt LINQ diese automatisch in eine Ordnerstruktur für Sie (Sie können diese Metadaten später nicht mehr verwenden). z.B.

var pageIndex = /* ??? */; 
var rows = db.tblExample 
      .OrderBy(x => x.SNo) 
      .Skip(pageIndex * 10).Take(10); 

, die man so etwas geben sollte: So, jetzt

SELECT [t1].[SNo] AS [SNo], 
     [t1].[Name] AS [Name], 
     [t1].[Age] AS [Age] 
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [t0].[tblExample], [t0].[SNo]) AS [ROW_NUMBER], 
     [t0].[SNo], 
     [t0].[Name], 
     [t0].Age] 
    FROM [tblExample] AS [t0] 
) AS [t1] 
WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1 
ORDER BY [t1].[ROW_NUMBER] 

die row_number innerhalb SQL intern verwendet wird, aber Sie sind nicht in der Lage den Zugriff auf sie innerhalb des Codes zu erhalten.

Wenn Sie diese Art von Zugriff wirklich möchten, ist es möglicherweise besser, die Abfrage manuell an den Server zu senden. Eine Lib, die gut mit dieser Art von Sache funktioniert, ist dapper-dot-net, die in etwa wie folgt aussehen würde:

+0

Eigentlich * können * Sie die Zeilennummer mit einer wenig bekannten Überladung von '.Select()', die in etwa so aussieht: '.Select ((x, i) => new {Index = i, Item = x}) ', was zu einem Objekt führt, wobei" obj.Index "die Zeilennummer ist. – anaximander

+0

@anaximander: Diese Überladung hat zwar keine SQL-Übersetzung, ist also nur gültig, solange die Daten _local_ sind. das heißt, wenn Sie 10k Datensätze haben, müssen Sie alle 10k in einem Aufzählungszeichen haben, bevor Sie die Überladung verwenden können. (Der Fehler, der auftritt, wurde als Kommentar zu D Stanleys Antwort aufgeführt) –

+0

In der Tat. Wenn Sie '.Skip()' und '.Take()' verwenden, verwenden Sie sie jedoch wahrscheinlich zum Paging. Der eigentliche Sinn des Paging besteht darin, die Ergebnismenge in verwaltbare Blöcke zu zerlegen. Wenn Ihre Seiten groß genug sind, dass das Laden der Sammlung in den Speicher ein Problem darstellt, führen Sie ein falsches Paging durch. – anaximander

Verwandte Themen