#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);
}
И, возможно, также перегрузка с помощью ключа сортировки.