微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么.ToPagedList工作如此缓慢?

如何解决为什么.ToPagedList工作如此缓慢?

我想知道分页在从数据库提取的数据集上到底如何工作。在我的示例中,我对表进行了一些搜索和过滤,然后将这些值传递给控制器​​。我还将page传递给.ToPagedList

我注意到分页的速度很慢(当我将页面切换到下一页时需要花费时间)。这就是为什么我要问.ToPagedList真正如何工作以及使用它有什么好处。

在我的示例中-每次更改页码Index时,都会调用操作并建立与数据库的连接。过滤整个数据集,然后结果变为PagedList。然后我可以看到我在给定的页面上,但确实需要时间。

当我更改页面时,再次-调用索引动作,它将连接到数据库并绘制数据集,过滤器并将结果返回给定页面。也许我错了,但是从性能上来说,这是一种很慢的方法,并且会占用大量内存。

查看:

@using PagedList.Mvc;
@model IPagedList<XYZ.Models.DocumentsModel>

// some code here

<tr>
@using (Html.BeginForm("Index","Home",FormMethod.Get))
{
<th>               
    @Html.TextBox("Account")
</th>   

<th>
    @Html.TextBox("Inv")
</th>

<th>
     @Html.DropDownList("filterList",new List<SelectListItem>
           {
            new SelectListItem { Text="",Value= "",Selected=true},new SelectListItem { Text="None",Value="None"},})
     
     <input type="button" class="search" value="filter" />

</th>
}
</tr>


@Html.PagedListPager(Model,page => Url.Action("Index",new
{
    page,Account = Request.QueryString["Account"],Invoice = Request.QueryString["Inv"],filterList = Request.QueryString["filterList"]

})

控制器:

public class HomeController : Controller
{
    private IDocuments _docs;

    public HomeController(IDocuments docs)
    {
        _docs = docs;
    }

    public ActionResult Index(int? page,string filterList,string Account,string Invoice)
    {
        var docsModel = _docs.GetAll();

        var model = docsModel.Where(w => String.IsNullOrEmpty(Account) || w.docsModel.FOPKTO.Contains(Account))
                             .Where(w => String.IsNullOrEmpty(Invoice) || w.docsModel.FOPLBN.Contains(Invoice))
                             .Where(w => String.IsNullOrEmpty(filterList) || w.docsModel.DECISION == filterList)
                             .Select(s => new DocumentsModel
                               {
                                   Account = s.docsModel.FOPKTO.Trim(),Date = s.docsModel.FOPBDA
                               })
                             .OrderBy(o => o.Date)
                             .ToPagedList(page ?? 1,15); 

    return View(model);
}

接口:

public class DocumentsService : IDocuments
{
    private MYdb _context;

    public DocumentsService(MYdb context)
    {
        _context = context;
    }

    public IEnumerable<DocumentsTablesql> GetAll()
    {
        return _context.DocumentsTablesql.AsNoTracking();
    }
}

如您每次更改页面时所看到的,将调用Index操作并查询数据库,这会花费时间和内存。我认为PagedList以某种方式保留结果,并且不允许在页面更改时一直查询数据库

编辑:

我在控制器代码和接口中添加了“ _docs”,以说明如何从数据库提取数据。我将依赖项注入控制器。

解决方法

我认为问题在于如何撰写您的选择。现在,您执行.Select(s => new DocumentsModel ...)时,列表将解析到内存中,并从数据库中获取所有行。 OrderBy()和ToPagedList()都在内存中的所有行上执行。下面,我使用系统上的本地数据库来处理您的应用程序。读取的表是“课程”,其中包含很多行。

执行下面的代码可获得以下结果:


Getting list 1 took 2289 milliseconds
Getting list 2 took 46 milliseconds

这是代码:

using System;
using System.Diagnostics;

namespace ToPagedList
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();

            sw.Start();

            var list1 = Repository.GetCourses1();

            sw.Stop();
            Console.WriteLine($"Getting list 1 took {sw.ElapsedMilliseconds} milliseconds");


            sw.Reset();
            sw.Start();

            var list2 = Repository.GetCourses2();

            sw.Stop();
            Console.WriteLine($"Getting list 2 took {sw.ElapsedMilliseconds} milliseconds");

            Console.ReadKey();
        }
    }
}

下面的代码的区别是您放置.Select()语句的位置。

  • 在第一个列表中,将整个表读入Select(),然后进行排序。
  • 在第二个列表中,仅读取表的15行。 OrderBy()是在数据库中完成的,而不是在内存中完成的。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ToPagedList
{
    public class Repository
    {
        public static List<DocumentsModel> GetCourses1(string school = null,string code = null,string title = null,int page = 0,int count = 15)
        {
            var courses = new DocumentModelEntities().Course;

            return courses.Where(course => string.IsNullOrEmpty(code) || course.CourseCode.Contains(code))
                                 .Where(course => String.IsNullOrEmpty(title) || course.Title.Contains(title))
                                 .Where(w => String.IsNullOrEmpty(school) || w.School == school)
                                 // From here your table is read from the DB using the where clauses
                                 .Select(s => new DocumentsModel
                                 {
                                     Code = code.Trim(),Title = s.Title
                                 })
                                 .OrderBy(o => o.Code)
                                 .Skip(page * count)
                                 .Take(count)
                                 .ToList();
        }

        public static List<DocumentsModel> GetCourses2(string school = null,int count = 15)
        {
            var courses = new DocumentModelEntities().Course;

            return courses.Where(course => string.IsNullOrEmpty(code) || course.CourseCode.Contains(code))
                             .Where(course => String.IsNullOrEmpty(title) || course.Title.Contains(title))
                             .Where(w => String.IsNullOrEmpty(school) || w.School == school)
                             .OrderBy(course => course.CourseCode)
                             .Skip(page * count)
                             .Take(count)
                             // From here your table is read from the DB using the where clauses,order by,skip and take
                             .Select(s => new DocumentsModel
                             {
                                 Code = code.Trim(),Title = s.Title
                             })
                             .ToList();
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。