Вопрос

Я озадачен этой простой проблемой с данными.

Я использую платформу Entity и имею базу данных продуктов.На моей странице результатов отображается постраничный список этих продуктов.Сейчас мои результаты упорядочены по количеству продаж каждого продукта, поэтому мой код выглядит так:

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 к результатам запроса?

Нет правильного решения

Другие советы

Использовать индексированная перегрузка 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 });

На самом деле использование OrderBy, а затем Skip + Take генерирует ROW_NUMBER в EF 4.5 (вы можете проверить с помощью SQL Profiler).

Я искал способ сделать то же самое, о чем вы просите, и смог получить то, что мне нужно, благодаря упрощению ответа Крейга:

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

Кстати, сгенерированный SQL использует ROW_NUMBER > start и 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();
    }
}

Если у вас это есть, вы можете «разбить на страницы» конкретную запрашиваемую коллекцию, используя это:

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top