如何将使用ROW_NUMBER()的查询转换为linq?

时间:2013-07-22 13:05:50

标签: c# 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 个答案:

答案 0 :(得分:7)

不是直接转换,但由于您的行号似乎仅用于分页,请尝试:

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

除了rowindex字段不会从SQL查询返回,而是由成员选择表达式添加之外,您应该最终得到等效的 SQL。 / p>

答案 1 :(得分:7)

您可以将查询编写为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();

答案 2 :(得分:0)

最佳情况(如果您需要元数据):

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会自动将其转换为rownumber(稍后您将无法使用该元数据)。 e.g。

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内部使用,但您无法在代码中访问它。

如果您真的想要这种访问,最好手动将查询发送到服务器。一个适合这类事情的lib是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() ... ) ...");