どのように私は、LINQクエリまたはエンティティにROW_NUMBERを追加するには?
-
19-09-2019 - |
質問
私はこの簡単なデータの問題で困惑しています。
私は、エンティティフレームワークを使用した製品のデータベースを持っています。私の結果ページでは、これらの製品のページ分割リストを返します。今の私の結果は、各製品の販売数が注文したので、私のコードは次のようになりますされます:
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列を追加するにはどうすればよいです?
正しい解決策はありません
他のヒント
実際のOrderByを使用して、(あなたがSQLプロファイラで確認することができます)+ TakeはEF 4.5でROW_NUMBERを生成スキップます。
私はあなたが求めている同じことを行う方法を探していたと私はクレイグの答えの簡素化を通じて必要なものを得ることができた。
var start = page * rowsPerPage;
Products.OrderByDescending(u => u.Sales.Count())
.Skip(start)
.Take(rowsPerPage)
.ToList();
ところで、生成されたSQLは、ROW_NUMBERを使用しています>起動して、TOP rowsPerPageます。
ここで長いったらしい答えがあります。まず、そのように番号/アイテムのペアを収容するためにクラスを作成します:
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();
}
}
あなたは「paginate」ができることをしたら、これを使用して、特定の照会可能なコレクションます:
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);
}
これを試してみてください。
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であなたのウェブサイトでカウントを開始します。