需求分析:如下图,共检索到1878条数据,但只显示第一页共50条,且无法点击下一页;所以就需要对此页面的查询功能进行修改,使其可以分页查询
分页原理:
在SQL语句处理完毕后,数据库,Web应用服务区(WebApplication)和客户端(Browser)都能进行分页,那在哪里分页好呢?
判断的标准是速度,显而易见,数据库服务器,Web应用服务器和客户端之间是网络,网络传递的数据量越少,则客户端获得响应的速度越快.而且一般来说,数据库服务器和Web应用服务器的处理能力一般比客户端要强很多.从这两点来看,在客户端分页的方案是最不可取的.
其次就剩下了在Web服务器端分页和在数据库端分页两种方式了,如果选择在Web服务器端分页的话,大部分的被过滤掉的数据还是被传输到了Web应用服务器端,与其这样还不如直接在数据库端进行分页.
因此比较好的分页做法应该是每次翻页的时候只从数据库里检索页面大小的块区的数据。这样虽然每次翻页都需要查询数据库,但查询出的记录数很少,网络传输数据量不大,如果使用连接池更可以略过最耗时的建立数据库连接过程。而在数据库端有各种成熟的优化技术用于提高查询速度,比在应用服务器层做缓存有效多了。
项目中的分页代码:
public ActionResult GetEquipmentRunningStateDayList(PagingArgument Argument, string createTimeStart, string createTimeEnd, string PSCode) { Pagination pagination = new Pagination(Argument.page, Argument.rows); PagedData<EM_EquipmentRunningState_Day> pagedData = this.CreateService<IEquipmentReportService>().GetEquipmentRunningStateDayList(pagination, PSCode, createTimeStart, createTimeEnd); var data = new { rows = pagedData.DataList, total = pagedData.TotalPage, page = pagination.Page, records = pagedData.TotalCount }; return Content(data.ToJson()); }
public PagedData<EM_EquipmentRunningState_Day> GetEquipmentRunningStateDayList(Pagination pagination, string PSCode, string createTimeStart, string createTimeEnd) { Expression<Func<EM_EquipmentRunningState_Day, bool>> exp = a => a.Id == a.Id; if (!string.IsNullOrEmpty(createTimeStart)) { DateTime pdate = Convert.ToDateTime(createTimeStart); exp = exp.And(a => a.Date >= pdate); } if (!string.IsNullOrEmpty(createTimeEnd)) { DateTime pdate2 = Convert.ToDateTime(createTimeEnd); exp = exp.And(a => a.Date < pdate2.AddDays(1)); } if (!string.IsNullOrEmpty(PSCode)) { exp = exp.And(a => a.PSCode == (PSCode)); } IQuery<EM_EquipmentRunningState_Day> StationData = this.DbContext.Query<EM_EquipmentRunningState_Day>().FilterDeleted(); PagedData<EM_EquipmentRunningState_Day> pagedate = StationData.Select((EM_EquipmentRunningState_Day) => new EM_EquipmentRunningState_Day { Id = EM_EquipmentRunningState_Day.Id, Date = EM_EquipmentRunningState_Day.Date, PSCode = EM_EquipmentRunningState_Day.PSCode, NormalTime = EM_EquipmentRunningState_Day.NormalTime, StandbyTime = EM_EquipmentRunningState_Day.StandbyTime, FailureTime = EM_EquipmentRunningState_Day.FailureTime, DownTime = EM_EquipmentRunningState_Day.DownTime }).Where(exp).OrderBy(it => it.Date).ThenBy(it => it.PSCode).TakePageData(pagination); return pagedate; }
看完上面两段代码所以分页的重点在于控制器中下面这段代码,给rows,total,page,records赋上正确的值就可以了
var data = new { rows = pagedData.DataList, total = pagedData.TotalPage, page = pagination.Page, records = pagedData.TotalCount };
那么这几个参数到底都是什么意思呢?
rows:页面上显示的数据
total:页面上显示的"共X页"中的总页数
page:页面上显示的当前页码
records:页面上显示的“检索到X条记录”中的总记录数
只要给以上几个参数赋值正确就能完成了分页。
rows页面上显示的数据是分页之后的,每次查询都去数据库做查询并在数据库分页,取出要查询的页数的数据赋值给rows即可。
public ActionResult GetMonthlyDeviceStatus(PagingArgument Argument, string createTimeStart, string createTimeEnd, string PSCode) { Pagination pagination = new Pagination(Argument.page, Argument.rows); List<EM_EquipmentRunningState_Month> dataList = this.CreateService<IEquipmentReportService>().GetMonthlyEquipmentRunningStateList(PSCode, createTimeStart, createTimeEnd); List<EM_EquipmentRunningState_Month> rowsList = this.CreateService<IEquipmentReportService>().GetEM_EquipmentRunningState_MonthList(pagination, PSCode, createTimeStart, createTimeEnd); var data = new { rows = rowsList,//当前页记录数 total = dataList.Count() % pagination.PageSize == 0 ? dataList.Count() / pagination.PageSize : dataList.Count() / pagination.PageSize + 1,//总页数 page = pagination.Page,//当前页 records = dataList.Count()//总记录数 }; return Content(data.ToJson()); }
public List<EM_EquipmentRunningState_Month> GetMonthlyEquipmentRunningStateList(string PSCode, string createTimeStart, string createTimeEnd) { List<EM_EquipmentRunningState_Month> data = null; try { string sql = ""; if (string.IsNullOrEmpty(PSCode)) { sql = @"SELECT row_number() OVER (ORDER BY w0.Date DESC,w0.PSCode ASC) n, w0.* FROM [dbo].[EM_EquipmentRunningState_Month] w0 where w0.Date >= '{0}'and w0.Date <= '{1}'"; data = this.DbContext.SqlQuery<EM_EquipmentRunningState_Month>(string.Format(sql, createTimeStart, createTimeEnd), null).ToList(); } else { sql = @"SELECT row_number() OVER (ORDER BY w0.Date DESC,w0.PSCode ASC) n, w0.* FROM [dbo].[EM_EquipmentRunningState_Month] w0 where w0.Date >= '{0}'and w0.Date <= '{1}' and w0.PSCode = '{2}'"; data = this.DbContext.SqlQuery<EM_EquipmentRunningState_Month>(string.Format(sql, createTimeStart, createTimeEnd, PSCode), null).ToList(); } } catch (Exception ex) { Console.WriteLine(ex.Message); } return data; }
public List<EM_EquipmentRunningState_Month> GetEM_EquipmentRunningState_MonthList(Pagination pagination, string PSCode, string createTimeStart, string createTimeEnd) { List<EM_EquipmentRunningState_Month> data = null; try { int Page = pagination.Page; int PageSize = pagination.PageSize; int start = (Page - 1) * PageSize; int end = Page * PageSize; string sql = ""; if (string.IsNullOrEmpty(PSCode)) { sql = @"select top {0} w2.* from ( SELECT row_number() OVER (ORDER BY w0.Date DESC,w0.PSCode ASC) n, w0.* FROM [dbo].[EM_EquipmentRunningState_Month] w0 where w0.Date >= '{1}'and w0.Date <= '{2}' ) w2 where w2.n > {3}"; data = this.DbContext.SqlQuery<EM_EquipmentRunningState_Month>(string.Format(sql, end, createTimeStart, createTimeEnd, start), null).ToList(); } else { sql = @"select top {0} w2.* from ( SELECT row_number() OVER(ORDER BY w0.Date DESC, w0.PSCode ASC) n, w0.* FROM[dbo].[EM_EquipmentRunningState_Month] w0 where w0.Date >= '{1}'and w0.Date <= '{2}' and w0.PSCode = '{3}' ) w2 where w2.n > {4}"; data = this.DbContext.SqlQuery<EM_EquipmentRunningState_Month>(string.Format(sql, end, createTimeStart, createTimeEnd, PSCode, start), null).ToList(); } } catch(Exception ex) { Console.WriteLine(ex.Message); } return data; }
sql server 分页的sql 语句 :https://www.jb51.net/article/35213.htm 我用的里面的第四个
ROW_NUMBER() OVER函数的基本用法:https://www.cnblogs.com/liuzhenlei/p/8026278.html
sql server 不同版本用的分页函数不同:https://www.cnblogs.com/xunziji/archive/2012/08/06/2625563.html