Как мне перевести запрос, который использует ROW_NUMBER(), на linq?

Моя таблица состоит из трех столбцов (sno,name,age). Я получаю эту таблицу из базы данных с дополнительным столбцом (номер строки), и я использовал следующий код:

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)

Обратите внимание, pageindex - это переменная, которая принимает некоторое целочисленное значение, которое передается пользователем.

Моя база данных Sql Server 2008. Я хочу написать тот же запрос, используя Linq. Как я могу это сделать?

3 ответа

Решение

Вы можете написать запрос как 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();

Не прямой перевод, но так как ваш номер строки используется только для подкачки, попробуйте:

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

РЕДАКТИРОВАТЬ

Если Select((t,i) => ...) не работает, вы можете попробовать синтезировать индексный номер, добавив его после гидратации запроса:

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 })

Вы должны получить эквивалентный SQL, кроме того факта, что rowindex поле не будет возвращено из запроса SQL, но вместо этого будет добавлено выражением выбора члена.

Лучший сценарий (если вам нужны метаданные):

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

Единственным недостатком здесь является то, что весь набор данных должен быть извлечен, чтобы получить эти метаданные. Однако, если вы используете .Skip & .Take LINQ автоматически переведет его в число для вас (вы просто не сможете использовать эти метаданные позже). например

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

что должно дать вам что-то вроде:

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]

Так что теперь row_number используется внутри SQL, но вы не можете получить к нему доступ в своем коде.

Если вы действительно хотите такой доступ, вам лучше вручную отправить запрос на сервер. Одна библиотека, которая хорошо работает с такими вещами, это dapper-dot-net, которая будет выглядеть примерно так:

class MyObject {
    public Int32 rowindex;
    public Int32 SNo;
    public String Name;
    publig Int32 Age;
}

/* build "connection" */

connection.Query<MyObject>("SELECT * FROM (SELECT ROW_NUMBER() ... ) ...");
Другие вопросы по тегам