2009-07-22 91 views
23

我被这个简单的数据问题困住了。如何将ROW_NUMBER添加到LINQ查询或实体?

我使用实体框架,并拥有产品的数据库。我的结果页面会返回这些产品的分页列表。现在我的结果是由销售每个产品的数量排序,所以我的代码如下所示:

return Products.OrderByDescending(u => u.Sales.Count()); 

这将返回我的实体,由销售数量排序的一个IQueryable数据集。

我希望我的结果页面显示每个商品的排序位次(中集)。我的结果应该是这样的:

Page #1 
1. Bananas 
2. Apples 
3. Coffee 

Page #2 
4. Cookies 
5. Ice Cream 
6. Lettuce 

我期待,我只是想在使用SQL ROW_NUMBER可变我的结果中添加一列...但我不知道如何将此列添加到我的结果数据表。

我的结果页会包含一个foreach循环,但由于我使用的是一套分页我用这个数字将假一等级数将不会是最好的办法猜测。

所以我的问题是,如何将ROW_NUMBER列在这种情况下,添加到我的查询结果?

回答

0

试试这个

var x = Products.OrderByDecending(u => u.Sales.Count()); 
var y = x.ToList(); 

for(int i = 0; i < y.Count; i++) { 
    int myNumber = i; // this is your order number 
} 

只要名单停留在相同的顺序,这应该发生,除非销售数量的变化。你可以得到一个准确的数字;

也有这样做的这样。

var page = 2; 
var count = 10; 
var startIndex = page * count; 

var x = Products.OrderByDecending(u => u.Sales.Count()); 
var y = x.Skip(startIndex).Take(count); 

这给出了页面的起始索引,再加上它给你一小部分的销售额显示在页面上。您只需在startIndex处开始计算您的网站。

25

使用indexed overload of Select

var start = page * rowsPerPage; 
Products.OrderByDescending(u => u.Sales.Count()) 
    .Skip(start) 
    .Take(rowsPerPage) 
    .AsEnumerable() 
    .Select((u, index) => new { Product = u, Index = index + start }); 
+1

哈哈。我亲手实施了这个方法,但这很有效。 – 2009-07-22 13:42:30

1

这是一个很长的解释。首先创建一个类来容纳数/项目对,像这样:

public class NumberedItem<T> 
{ 
    public readonly int Number; 
    public readonly T Item; 

    public NumberedItem(int number, T item) 
    { 
     Item = item; 
     Number = number; 
    } 
} 

接下来是一个抽象项目的页面各处(编号与否):

class PageOf<T> : IEnumerable<T> 
{ 
    private readonly int startsAt; 
    private IEnumerable<T> items; 

    public PageOf(int startsAt, IEnumerable<T> items) 
    { 
     this.startsAt = startsAt; 
     this.items = items; 
    } 

    public IEnumerable<NumberedItem<T>> NumberedItems 
    { 
     get 
     { 
      int index = 0; 
      foreach (var item in items) 
       yield return new NumberedItem<T>(startsAt + index++, item); 
      yield break; 
     } 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     foreach (var item in items) 
      yield return item; 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 
} 

一旦你有,你可以“分页”使用这个特定的可查询集合:

class PaginatedQueryable<T> 
{ 
    private readonly int PageSize; 
    private readonly IQueryable<T> Source; 

    public PaginatedQueryable(int PageSize, IQueryable<T> Source) 
    { 
     this.PageSize = PageSize; 
     this.Source = Source; 
    } 

    public PageOf<T> Page(int pageNum) 
    { 
     var start = (pageNum - 1) * PageSize; 
     return new PageOf<T>(start + 1, Source.Skip(start).Take(PageSize)); 
    } 
} 

最后一个不错的扩展方法来掩盖丑陋:

static class PaginationExtension 
{ 
    public static PaginatedQueryable<T> InPagesOf<T>(this IQueryable<T> target, int PageSize) 
    { 
     return new PaginatedQueryable<T>(PageSize, target); 
    } 
} 

这意味着你现在可以这样做:

var products = Products.OrderByDescending(u => u.Sales.Count()).InPagesOf(20).Page(1); 

foreach (var product in products.NumberedItems) 
{ 
    Console.WriteLine("{0} {1}", product.Number, product.Item); 
} 
1

实际使用排序依据,然后跳到+参加EF 4.5生成ROW_NUMBER(你可以用SQL事件探查器检查)。

我正在寻找一种方法可以做到你所要求的同样的事情,我能得到什么,我需要通过克雷格的答案的简化:

var start = page * rowsPerPage; 
Products.OrderByDescending(u => u.Sales.Count()) 
    .Skip(start) 
    .Take(rowsPerPage) 
    .ToList(); 

顺便说一句,生成的SQL用途ROW_NUMBER>开始和TOP rowsPerPage。