ASP.NET MVC Webgrid Эффективный пейджинг
У меня есть проект ASP.NET MVC 4 и SQL View (vvItem). ItemController
MVCAppEntities db = new MVCAppEntities();
public ActionResult Index()
{
var itemqry = db.vvItem.OrderBy(s => s.name);
//var pageditems = itemqry.Skip(10).Take(20); // 25 seconds
return View(itemqry.ToList()); // 88 seconds
}
Index.cshtml View
@model IEnumerable<MVCApplication1.Models.vvItem>
@{
var norows = 20;
var grid = new WebGrid(Model, canPage: true, rowsPerPage: norows);
grid.Pager(WebGridPagerModes.NextPrevious);
@grid.GetHtml(tableStyle: "table", headerStyle: "header", columns: grid.Columns(
grid.Column(columnName: "name", header: "Name", canSort: true),
grid.Column(columnName: "quantity", header: "Quantity", canSort: true),
grid.Column(columnName: "code", header: "Code", canSort: true),
grid.Column(columnName: "Price", header: "Price", canSort: true),
))}
Во vvItem у меня почти 400000 записей. Я думал, что пейджер веб-сетки будет загружать (Take()) только отображаемые записи, и он будет знать, чтобы пропустить () первые записи, если я перейду на следующие страницы.
Q: Как я могу эффективно создать представление для загрузки только отображаемых записей?
Я нашел 2 решения: версия JSON и NerdDinner
Я не очень хорош в JSON, поэтому я попробовал решение NerdDinner. И как в моей прокомментированной строке //var pageditems = itemqry.Skip(10).Take(20);
В itemqry уже загружены все записи, и загрузка заняла много времени.
Q2: Как я могу сделать пейджинг сейчас? Мне нужно изменить страницу нет. из метода индекса.
public ActionResult Index(int? page, string filter1 = " ", string filter2 = " ")
4 ответа
Я сделал хранимую процедуру SQL
CREATE PROCEDURE SkipTake
@pagNo int,
@pageSize int
AS
select *
from (select *, row_number() over (order by COD) as rn
from vvSTOC
) as T
where T.rn between (@pagNo - 1) * @pageSize + 1 and @pagNo * @pageSize
Я добавил этот sp в мою модель EF при импорте функций, чтобы он возвращал сущность (vvSTOC)
public ActionResult Index(int? page)
{
const int pageSize = 20;
return View(db.spSkipTake(page, pageSize).ToList());
}
Он не должен выполнять запрос сразу, пока itemqry имеет тип IEnumerable или IQueryable. Можете ли вы привести его к IQueryable следующим образом?
public ActionResult Index()
{
IQueryable<vvItem> itemQry = db.vvItem;
return View(itemQry.OrderBy(s => s.name).Skip(10).Take(20).ToList());
}
Если itemqry является правильным типом, он не будет выполнен, пока не будет вызван.ToList(), который преобразует его в тип IList. Проверьте SQL, который производится, чтобы быть уверенным.
Спасибо за это.
Я настроил это для работы с некоторыми входными параметрами в моем SP для управления PageSize, PageNumber, SortIndex и SortOrder:
declare @sql nvarchar(1000) = '
select * from
(
select *, row_number() over(order by '+@SortIndex+' '+@SortOrder+') as RowNumber from #Results
) as T
where T.RowNumber between ('+@PageNumber+' - 1) * '+@PageSize+' + 1 and '+@PageNumber+' * '+@PageSize
exec sp_executesql @sql
public ActionResult Index(int? pageIndex)
{
int pageSize = 20;
var itemIndex = ((pageIndex??1) -1) * pageSize;
return View(db.vvItem.OrderBy(s => s.name).Skip(itemIndex).Take(pageSize).ToList());
}