我想知道分页在从数据库中提取的数据集上到底如何工作。在我的示例中,我对表进行了一些搜索和过滤,然后将这些值传递给控制器。我还将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”,以说明如何从数据库中提取数据。我将依赖项注入控制器。
答案 0 :(得分:3)
我认为问题在于如何撰写您的选择。现在,您执行.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()语句的位置。
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, 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)
.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();
}
}
}