Как мне перевести запрос, который использует 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() ... ) ...");