Запрос LINQ для упорядочения элементов между двумя переменными

#json #asp.net-mvc #linq

Вопрос:

здесь полный новичок.
Я пытаюсь создать JsonResult, который я пытаюсь вернуть между двумя переменными. Вот действие:

 public JsonResult GetVoices(int? PageNumber, int? PageSize)
        {
            var StartRow = ((PageNumber - 1) * PageSize)   1;
            var EndRow = PageNumber * PageSize;
            var i = 0;
            var data = (from a in db.Content
                        select new
                        {
                            RowNumber = i  ,
                            Id = a.Id,
                            Title = a.Title,
                            Description = a.Description,
                            CreatedAt = a.CreatedAt
                        }).ToList();
            return Json(data, JsonRequestBehavior.AllowGet);
        }
 

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

Комментарии:

1. Ищите вопросы по подкачке LINQ и смотрите, как использовать Skip/Take.

2. Спасибо, посмотрел, и, похоже, это может решить проблему

Ответ №1:

Вы ищете что-то вроде этого:

 public JsonResult GetVoices(int PageNumber, int PageSize) =>
    Json((from a in db.Content.ToArray()
         let StartRow = ((PageNumber - 1) * PageSize)   1
         let EndRow = PageNumber * PageSize
         from RowNumber in Enumerable.Range(StartRow, EndRow - StartRow   1)
         select new
         {
             RowNumber = RowNumber,
             Id = a.Id,
             Title = a.Title,
             Description = a.Description,
             CreatedAt = a.CreatedAt
         }).ToList(), JsonRequestBehavior.AllowGet);
 

Ответ №2:

Итак , у вас есть a PageSize и a PageNumber , и вам нужны все строки, которые находятся на странице PageNumber .

  • Страница 0 содержит строки от 0 до размера страницы — 1
  • Страница 1 содержит строки размером до 2 * Размер страницы — 1
  • Страница 2 содержит строки 2 * Размер страницы до 3 * Размер страницы — 1
  • и т.д.

Это, по-видимому, очень распространенная проблема, поэтому давайте не будем ограничиваться решением только этой проблемы, давайте сделаем решение, подходящее для всех последовательностей, на которые необходимо разделить pages .

Мой совет состоял бы в том , чтобы создать метод расширения IQueryable<T> , чтобы вы могли переплетать разбиение на страницы с другими методами LINQ. Если вы не знакомы с методами расширения, подумайте о том, чтобы прочитать Методы расширения, демистифицированные

Ввод: последовательность похожих элементов: IQueryable<T> , a PageSize и a PageNumber .

Вывод: все строки на странице PageNumber , в соответствии с приведенным выше определением. Таким образом, на каждой странице, кроме последней, есть PageSize количество строк. На последней странице будет Total number of rows % PageSize

Я решил вернуться IQueryable<T> , но нет ICollection<T> . Это имеет то преимущество, что если вы не перечисляете строки на странице, данные не извлекаются. Недостатками является то, что вам нужно рассчитать количество строк на каждой странице и количество страниц. Если вы думаете, что всегда будете перечислять все строки на всех страницах, подумайте о возврате ICollection<T> .

 public IQueryable<T>> FetchPage<T>(
    this IQueryable<T> source,
    int pageNumber,
    int pageSize)
{
    // TODO: check input parameters: source not null, pageSize > 0, pageNumber >= 0

    return source.Skip(pageNumber * pageSize)
                 .Take(pageSize);
}
 

Использование: если у вас есть таблица продуктов, и вы хотите разделить ее на страницы размером 25, и вы хотите получить страницу 3, сначала с самыми дешевыми продуктами:

 IQueryable<Product> productsOnPage3 = dbContext.Products
    .OrderBy(product => product.Price)
    .FetchPage(3, 25)
    .ToList();
 

Если вам не нужна полная строка на ваших страницах, вы можете добавить a Select .

Рассмотрите возможность создания методов расширения с параметрами selector , как в LINQ Select:

 public IQueryable<T>> FetchPage<T>(
    this IQueryable<T> source,
    int pageNumber,
    int pageSize,
    Expression<Func<TSource,TResult>> selector)
{
    // TODO: check input parameter selector

    return source.FetchPage(pageNumber, pageSize)
                 .Select(selector);
}
 

И, возможно, также перегрузка с помощью ключа сортировки.