MVC学习(四)几种分页的实现(2)
在第一种分页方式中,仅仅实现了分页,但并未有体现出MVC的优势,没有体现出泛型编程思想,尤其在数据量很大的时候,分页十分缓慢,除此之外,还没有实现很好的封装,不是一个通用方法。
因此,我希望只要传入数据源以及页码数(采用泛型编程)便可以实现分页功能,且使用十分的方便。
下面就讲讲我的一些理解。
在泛型编程中,数据容器一般继承了IQueryable或者IEnumerable接口(此例中,数据源暂时继承了这两种接口)。
为了调用方法方便,我决定对这两个接口写扩展方法。
首先为了实现数据分页功能,我们常常需要考虑以下六个属性
总页数(TotalPage)、总数据量(TotalCount)、当前页码(PageIndex)、
一页显示数据多少(PageSize)以及上一页或者下一页(IsPreviousPage/IsNextPage)。
因此,基于对象属性,抽象出接口(IPageList),分页方法必须继承并实现这些属性。
接口IPageList代码如下
public interface IPageList
{
int TotalPage //总页数
{
get;
}
int TotalCount//总数量
{
get;
set;
} int PageIndex//第几页
{
get;
set;
} int PageSize//一页显示几条数据
{
get;
set;
} bool IsPreviousPage//是否上一页
{
get;
} bool IsNextPage
{
get;
}
}
IPageList
实现接口,代码如下:
public class PagedList<T>:List<T>:IPageList
{
public int TotalPage
{
return (int)Math.Ceiling((doubule)TotalCount/PageSize);
}
public int TotalCount
{
get; set;
}
public int PageIndex
{
get;
set;
} public int PageSize
{
get;
set;
} public bool IsPreviousPage
{
get { return (PageIndex>); }
}
public bool IsNextPage
{
get { ((PageIndex) * PageSize) < TotalCount; }
}
}
PagedList
让我们看看这句代码" public class PagedList<T>:List<T>:IPageList ",这里我们定义了一个泛型类PagedList<T>,
(其中T是一个关键字,T的类型可以是引用类型,也可以是值类)。在本例子,T是一个引用类型,而且是一个Model。
首先写一个静态类,然后在这个静态类中书写静态方法。扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 扩展方法是一种特殊的静态方法,因此,扩展方法应该放在一个静态类中。
好,首先对IQueryable<T>进行扩展,命名方法名称为 ToPagedList,一步一步的解析。
返回值应该是一个泛型集合,因此,方法名可以这样写
public List<T> ToPagedList<T>(this IQueryable<T> source,int? index,int? pageSize){ }
在这里,我们可以看到,数据源的类型是IQueryable<T>,页码数index是可空类型(默认第一页),每页数据条目pageSize可空类型,默认10条数据。
那么,如何调用这些方法的?
初学泛型编程确实挺麻烦,思考的方式不太一样,特别是代码的写法比较特殊,如果把泛型类当做普通的类来思考,就比较容易。
我们需要一个类的属性时,怎么去实例化呢(剔除静态类)? 很显然,new一个新的实例,然后去调用这个属性(我们写web Form页面写多了,很少考虑服务器控件是如何初始化的);如果想全部实例化属性,则需要在重载构造函数中动动手脚了。
那么,我们需要从构造函数中得到什么呢, 这才是重点。
第一,实例化分页的各个属性;第二,得到当前页码的数据,就这两件终级任务。
由于我希望传入数据源以及页码数便可获得分页数据,且考虑是在Asp.net MVC中,因此,传入的数据要么是IQueryable<T>,要么是IEnumerable<T>,故完全可以充分利用已经存在的类型属性为自己服务(相信微软写出的代码运行效率不会太低)。在这里我会重载两个构造函数,因为传入的数据源的类型不同。
我们 写上我们需要的构造函数,第一个参数:数据源,第二个参数:当前页码数,第三个参数每页显示几条数据。
这里的数据源很重要,因为要继承IQueryable或IEnumerable接口(这里需要写两个构造函数),以便可以使用不同的数据源。
首先看数据源是IQueryable的构造函数,代码如下
public PagedList(IQueryable<T> source, int? pageIndex, int? pageSize)
{
if (pageIndex == null) { pageIndex = ; }//默认显示第一页数据
if (pageSize == null) { pageSize = ; }//默认每页显示10条数据
this.TotalCount = source.Count();
this.PageSize = pageSize.Value;
this.PageIndex = pageIndex.Value; if (IsPreviousPage == false)
{
pageIndex = ;
} if (IsNextPage == false)
{
pageIndex = TotalPage;
}
int BeforePageIndex = pageIndex.Value - ;
if (BeforePageIndex < )
{
BeforePageIndex = ;
}
AddRange(source.Skip((BeforePageIndex) * pageSize.Value).Take(pageSize.Value));
//如果Index是0会报错,不能够是负数
}
public PagedList(IQueryable source, int? pageIndex, int? pageSize)
这里其实是将某一页的数据放入了List了,因为PagedList已经继承了List。
既然PagedList是一个List,那么实例化后返回的值便是我们需要的数据,考虑这点,前面的ToPagedList方法返回的值就需要具体一点,而不是模糊的List<T>,应该是PagedList<T>,因此,用于对IQueryable扩展,方法也应该是静态方法,修订后的方法如下
public static class Pagination
{
/// <summary>
/// 返回第几页的数据
/// </summary>
/// <typeparam name="T">返回的数据类型</typeparam>
/// <param name="source">数据源,数据源需继承IQueryable接口</param>
/// <param name="index">第几页</param>
/// <param name="pageSize">每页显示的数据条数,默认每页显示10条数据</param>
/// <returns></returns>
public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int? index, int? pageSize)
{
return new PagedList<T>(source, index, pageSize);
}
}
public static class Pagination
分页类准备好后,就是调用了。直接看代码吧
public ActionResult FY2(string GoFlag, string PageIndex)
{
int PageSize = ;
int TotalCount = LzsDB.MyTestPages.Count();//获得此数据表中数据记录数
double PageCount = Math.Ceiling((double)TotalCount / (double)PageSize);//获得总页数
int NowPageIndex = ;
if (!string.IsNullOrEmpty(PageIndex))
{
int ErrorPageIndex = ;
if (!Int32.TryParse(PageIndex, out ErrorPageIndex))//如果不能转换成整数,则默认当前页码为1
{
PageIndex = "";
} NowPageIndex = Convert.ToInt32(PageIndex);//
}
GoFlag = string.IsNullOrEmpty(GoFlag) ? "First" : GoFlag; switch (GoFlag)
{
case "First":
ViewBag.P2Index = ;
NowPageIndex = ;
break;
case "Pre": ViewBag.P2Index = Convert.ToInt32(PageIndex) - ;
NowPageIndex = Convert.ToInt32(PageIndex) - ; break;
case "Next":
ViewBag.P2Index = Convert.ToInt32(PageIndex) + ;
NowPageIndex = Convert.ToInt32(PageIndex) + ; break;
case "Last":
ViewBag.P2Index = PageCount;
NowPageIndex = Convert.ToInt32(PageCount);
break;
} var MyTestPagesList = LzsDB.MyTestPages.OrderBy(a => a.Id);
return View(MyTestPagesList.ToPagedList(NowPageIndex, ));
}
FY2(string GoFlag, string PageIndex)
分页后的效果如下
我插入了120万条数据,每页显示5条,在本机测试,分页还是蛮快的。
整个源程序点此下载,本例子是vs2010,MVC3,配置好数据库便可运行。
MVC学习(四)几种分页的实现(2)的更多相关文章
- MVC学习四:Razor视图语法
@{ Layout = null; } <hr /> <!DOCTYPE html> @this.GetType().Assembly.Location.ToString() ...
- MVC学习四
第七节 讲述了增加model中类的属性,由于数据库中已存在表,表中没有存在新加的列,所以可以删除数据库或者在数据库中新增一列,另可以在controller中新增一个数据库初始化的类,并在Globa ...
- spring MVC 学习(四)---拦截器,视图解析器
1.接口HandlerInterceptor 该接口包含3个方法,分别是preHandle,postHandle,afterCompletion,分别代表着执行前,执行后,执行完成要执行的方法,其中p ...
- MVC学习(四)几种分页的实现(3)
在这篇MVC学习(四)几种分页的实现(2)博文中,根据URL中传入的两个参数(页码数,首页.上一页.下一页.末页的标记符)来获得对应的分页数据, 只是传入的参数太多,调用起来不太方便(标记符不能够写错 ...
- sqlserver的四种分页方式
第一种:ROW_NUMBER() OVER()方式 select * from ( select *, ROW_NUMBER() OVER(Order by ArtistId ) AS RowId f ...
- asp.net mvc 的几种分页Pager
第一种 /// <summary> /// 分页Pager显示 /// </summary> /// <param name="html">&l ...
- ASP.NET MVC中有四种过滤器类型
在ASP.NET MVC中有四种过滤器类型
- .NET MVC 学习笔记(四)— 基于Bootstarp自定义弹出框
.NET MVC 学习笔记(四)—— 基于Bootstarp自定义弹出框 转载自:https://www.cnblogs.com/nele/p/5327380.html (function ($) { ...
- Java开发学习(四十一)----MyBatisPlus标准数据层(增删查改分页)开发
一.标准CRUD使用 对于标准的CRUD功能都有哪些以及MyBatisPlus都提供了哪些方法可以使用呢? 我们先来看张图: 1.1 环境准备 这里用的环境就是Java开发学习(四十)----MyBa ...
随机推荐
- 【转载-好文】使用 Spring 2.5 注释驱动的 IoC 功能
在 IBM Bluemix 云平台上开发并部署您的下一个应用. 开始您的试用 原文链接:https://www.ibm.com/developerworks/cn/java/j-lo-spring25 ...
- 无法作为数据库主体执行,因为主体 "dbo" 不存在、无法模拟这种类型的主体,或您没有所需的权限。 已将数据库上下文更改为
右键删除发布时报错信息: 其他信息:执行 Transact-SQL 语句或批处理时发生了异常. (Microsoft.SqlServer.ConnectionInfo)——————————无法作为数据 ...
- java连接mysql :No Suitable Driver Found For Jdbc 解决方法
今天出现编码出现了No suitable driver found for jdbc,又是找遍了网上的资料,基本上都说是以下个问题: 一是:连接URL格式出现了问题(Connection con ...
- springboot + swagger
swagger用于定义API文档. 好处: 前后端分离开发 API文档非常明确 测试的时候不需要再使用URL输入浏览器的方式来访问Controller 传统的输入URL的测试方式对于post请求的传参 ...
- 整合Apache+PHP教程
首先修改Apache的配置文件,让Apache支持解析PHP文件,Apache配置文件在Apache安装目录的conf目录下的httpd.conf,打开此文件, 找到#LoadModule,在这个下面 ...
- repeat语句
一.repeat语句格式repeat语句用于"重复执行循环体,直到指定的条件为真时为止" repeat语句格式:repeat 语句1; 语句2; -- 语句n;until ...
- [SharpZipLib 未能加载文件或程序集] 解决方法
未能加载文件或程序集"ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6a ...
- Apache性能优化、超时设置,linux 重启apache
在httpd.conf中去掉Include conf/extra/httpd-default.conf前的#以使httpd-default.php生效.其中调节以下参数Timeout 15 (连接超时 ...
- Lua 5.1 参考手册
Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes 云风 译 www.codingno ...
- 2.2 节的练习--Compiler principles, technologys, &tools
2.2 节的练习 2.2.1 考虑下面的上下文无关文法: S -> S S + | S S * | a 试说明如何使用该文法生成串 aa+a* 试为这个串构造一颗语法分析树 ⧗ 该文法生成的语言 ...