我被这个简单的数据问题难住了。
我正在使用实体框架并拥有一个产品数据库。我的结果页面返回这些产品的分页列表。现在我的结果是按每种产品的销售数量排序的,所以我的代码如下所示:
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 列?
没有什么可以直接转换为 LINQ to Entities 中的
ROW_NUMBER
。作为内存中的解决方法,您可以使用 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 });
实际上,在 EF 4.5 中使用 OrderBy 然后 Skip + Take 会生成 ROW_NUMBER(您可以使用 SQL Profiler 检查)。
我正在寻找一种方法来完成你所要求的同样的事情,并且我能够通过简化克雷格的答案来得到我需要的东西:
var start = page * rowsPerPage;
Products.OrderByDescending(u => u.Sales.Count())
.Skip(start)
.Take(rowsPerPage)
.ToList();
顺便说一句,生成的 SQL 使用 ROW_NUMBER > start 和 TOP rowsPerPage。
试试这个
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 处开始计数即可。
这是一个冗长的答案。首先创建一个类来容纳数字/项目对,如下所示:
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);
}