【问题标题】:ASP.NET MVC Webgrid Efficient PagingASP.NET MVC Webgrid 高效分页
【发布时间】:2012-06-21 11:45:46
【问题描述】:

我有一个 ASP.NET MVC 4 项目和一个 SQL 视图 (vvItem)。 物品控制器

    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 视图

@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 条记录。我认为 webgrid Pager 只会加载 (Take()) 显示的记录,如果我要转到下一页,它会知道 Skip() 第一条记录。

:如何有效地使视图仅加载显示的记录?

我找到了 2 个解决方案:JSON versionNerdDinner

我不太擅长 JSON,所以我尝试了 NerdDinner 解决方案。正如我的评论行 //var pageditems = itemqry.Skip(10).Take(20); itemqry 已经加载了所有记录,加载需要很长时间。

Q2:我现在如何进行分页?我需要修改页码。来自 Index 方法。

public ActionResult Index(int? page, string filter1 = " ", string filter2 = " ")

【问题讨论】:

  • 在 nerddinner 示例中,他们将在视图中实现 x 而不是 itemqry。
  • 我将 x 重命名为 pageditems。如您所见,使用 Skip-Take 需要 25 秒,而没有 88 秒
  • 对于问题 2,它将在控制器中进行管理,如 NerdDinner 示例和下面发布的 user1439338 所示。您的视图必须计算页面数量并管理页面链接。如 NerdDinner 链接底部所示,专用视图模型是一种好方法。

标签: asp.net-mvc pagination webgrid skip-take


【解决方案1】:

只要 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 以确保确定。

【讨论】:

  • 你在我回来的评论行中写下了我的内容。我在没有 Skip() 和 Take() 的情况下计时了 1 分半钟,使用 Skip() 和 Take() 计时了 25 秒。在 SQL 中,从同一个表中,如果我写 TOP 1000,它将在 1 秒内返回 1000 行
  • 如果在 Visual Studio 中将鼠标悬停在 itemqry 上,它是什么类型的变量?
  • {System.Data.Objects.ObjectQuery}
  • 我对 ObjectQuery 不太熟悉,但听起来它在延迟执行方面表现不佳。这是令人惊讶的,因为它实现了 IQueryable 接口。我会用另一个建议更新答案。
【解决方案2】:

我做了一个 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

我在函数导入的 EF 模型中添加了这个 sp,以便它返回一个实体 (vvSTOC)

    public ActionResult Index(int? page)
    {
        const int pageSize = 20;
        return View(db.spSkipTake(page, pageSize).ToList());
    }

【讨论】:

  • 这是 SP 版本。如果您有其他解决方案,请填写我。
  • db对象是如何定义的?
  • 我有一个 SQL 表和一个 SQL 视图(视图显示来自这个表的行加上来自另一个表的一些不重要的数据(~ 1000 条记录))有 ~ 400.000 条记录。您想查看视图和表中的 SQL 脚本吗?
  • 不,你在上面回答了我的问题,我想我现在明白了。
  • @Misi 你能解释一下这是如何在视图中显示的/如何在视图中显示分页结果(当我们以 SP 方式进行时)??
【解决方案3】:
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()); 
}

【讨论】:

    【解决方案4】:

    谢谢。

    我对此进行了调整,以使用我的 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
    

    【讨论】:

      猜你喜欢
      • 2011-05-10
      • 2011-07-03
      • 2012-05-14
      • 2018-03-09
      • 2011-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多