2009-07-22 70 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。