it
分类:
2012-03-27 08:40:25
原文地址:学习之路九:深入剖析Web分页原理 作者:逊云锋
这段时间因为项目需要,要做一个分页的功能,说实话这类的文章在园子里面可以说是满天飞了,为什么要写呢?没什么高深的技术,只是做个总结,把那些零零碎碎的问题整合起来,好给大家一个完整的参考吧!
这是我第一次自动动手写分页,所以这样的文章适合跟我一样的小菜阅读....
1.分页的最基本参数
总页数 → PageTotalCount //查询的结果分页之后有多少页
总记录数 → RecordTotalCount //查询的结果包含多少条记录
每一页的记录数 → DisplayRecordCount //每一页显示多少条记录数
一次显示多少页数 → DisplayPageCount //一次加载显示多少个页数,五个或者十个等等
首页和末页 → FirstPage ,LastPage //快速回到第一页以及最后一页的按钮
上一页和下一页 → UpPage,NextPage //下一页和上一页
页索引号 → IndexPage //用户当前点击的页号码 |
Note:这只是最基本的参数,还有很多的查询参数需要我们按照自己的项目需求来定义!
Note:对于总记录数的获取我的方案是使用输出参数来获取!
2.在URL地址中传入分页参数实现分页
2.1 原理:
主要是通过获取URL中的参数值来判断用户点击的是第几页!
2.2 机制:
通过查看HTML代码,发现每一个分页按钮的超链接都是这样写的,如:
博客园分页源代码:
所以这种的方式还是比较常用的!
2.3 原理分析:
①所有的HTML的代码在后台进行组装,然后在页面加载的时候进行输出!
②每个超链接的href属性都在后台进行赋值!
③对一些复杂的业务逻辑进行有效处理!
2.4 解决点击“...”按钮的问题,说实话这里面的逻辑还是有点复杂的,我搞了好久才弄清楚了:
这边涉及到一个层的概念(不是标准术语),所谓的层就是一个页面一次性显示的的总页数!
Note: 层的层次关系:
1,2,3 … 10; 第一层 索引号为“0”
11,12,13 … 20; 第二层 “1”
21,22,23 … 30; 第三层 “2”
如果说你的总页数有98页,每一次显示10页,那么分页的总层数就为 → int pageLevelCount = 98 % 10 ==0 ? 98 / 10 : 98 / 10 + 1
有如下几个核心代码:
下面的代码是判断页面上时候有“...”的按钮:
如果能够把这些逻辑搞清楚了,分页也就不算太难了!
下面是全部代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145 |
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Data;
using System.Text.RegularExpressions;
using System.Text;
namespace Web分页原理学习Demo
{
public partial class _Default : System.Web.UI.Page
{
public int totalCount = 0;
public int pageIndex = 1;
public string pageHTML = "";
string url = HttpContext.Current.Request.Url.AbsoluteUri;//当前页面绝对路径
protected void Page_Load(object sender, EventArgs e)
{
string QueryStringName = Request.QueryString["page"];
//QueryStringName = QueryStringName == null ? "1" : QueryStringName;
//首先先获取URL
//""
pageIndex = QueryStringName == null ? 1 : Convert.ToInt32(QueryStringName);
//对URL进行一些设置
if (url.Contains("aspx?"))
{
if (Regex.IsMatch(url, @"page=[0-9]*$", RegexOptions.IgnoreCase))//如果存在page=*的字符串
{
url = Regex.Replace(url, @"page=[0-9]*$", "", RegexOptions.IgnoreCase);//替换掉page=*的字符串
}
url += "page" + "={0}";
}
else
{
url += "?" + "page" + "={0}";
}
//if (!url.Contains("page"))
//{
// url += "?page={0}";
//}
this.Repeater1.DataSource = GetData(pageIndex);
this.Repeater1.DataBind();
pageHTML = GetPageHTML(totalCount, pageIndex, url);
}
public DataTable GetData(int pageIndex)
{
DataTable dt = new DataTable();
string connString = @"server=22610800E100468;integrated security = SSPI;database=Northwind";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "MyPage";
cmd.Parameters.Add(new SqlParameter("@pageIndex", pageIndex));
SqlParameter para = new SqlParameter();
para.ParameterName = "@recordTotalCount";
para.DbType = DbType.Int32; //必须指明参数类型
para.Direction = ParameterDirection.Output;
cmd.Parameters.Add(para);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
totalCount = (int)da.SelectCommand.Parameters["@recordTotalCount"].Value;
}
return dt;
}
//开始填充HTML代码
public string GetPageHTML(int recordTotalCount, int pageIndex, string url)
{
StringBuilder strBuilder = new StringBuilder(1000);
string attr = "";
int pagecount = 0;//当前页面的总层数
int floorcount = 0;//分页的总层数
int currentLastPage = 0;//当前最后一页的页码,用来保存最后一页的号码
//总页数
int pageTotalCount = recordTotalCount / 10 + 1;
strBuilder.Append("
");
attr = pageIndex == 1 ? "visible=\"" + "false\"" : ""; //标志当前页第一页是否相等 来控制前俩个按钮的有效性
strBuilder.AppendFormat(GetAHtml(attr, string.Format(url, 1), "首页"));
strBuilder.AppendFormat(GetAHtml(attr, string.Format(url, pageIndex - 1), "上一页"));
pagecount = pageIndex / 10;//当前页数 0~1~2
pagecount = pageIndex % 10 == 0 ? pagecount - 1 : pagecount;//清除当 当前页数为分页页码数的整数倍页时除数多一的状况
floorcount = pageTotalCount / 10;//页面层数 0~1~2
currentLastPage = pageTotalCount < 10 * (pagecount + 1) ? pageTotalCount : 10 * (pagecount + 1);
if (pageIndex > 10) //对也按钮的设置
{
strBuilder.AppendFormat(GetAHtml("", string.Format(url, 10 * pagecount), "..."));
}
for (int i = 10 * pagecount + 1; i < currentLastPage; i++)
{
if (i == pageIndex)
{
strBuilder.AppendFormat(GetSpanHtml(i, ""));
}
else
{
strBuilder.AppendFormat(GetAHtml("", string.Format(url, i), i.ToString())); //设置超链接
}
}
if (pageIndex <= 10 * floorcount) //当当前序号小于倒数第二页页码时显示在后端...
{
strBuilder.AppendFormat(GetAHtml("", string.Format(url, 10 * (pagecount + 1) + 1), ""));
}
attr = pageIndex == pageTotalCount ? "visible=\"" + "false\"" : "";//标志当前页最后一页是否相等 来控制后俩个按钮的有效性
strBuilder.AppendFormat(GetAHtml(attr, string.Format(url, pageIndex + 1), "下一页"));
strBuilder.AppendFormat(GetAHtml(attr, string.Format(url, pageTotalCount), "末页"));
strBuilder.AppendFormat(" "); return strBuilder.ToString();
}
///
/// get the html of a label
///
/// a's title
/// the url of a
/// the attribute
///
private static string GetAHtml(string attr, string url, string title)
{
return "" + title + "\n";
}
//这个方法的目的是固定住当前用户点击的页索引
private static string GetSpanHtml(int num, string className)
{
return "" + num + "\n";
}
}
} |
3.分页存储过程深入学习
3.1 定义表变量来存储数据,实现分页
Note:自SQL Server2005之后出来了“CTE”的语法,大家也可以使用这种方式来进行分页!
3.2 使用“Top”和“In”
3.3 使用“Row_Number() Over(Order By [字段名] DESC)”
Note:你可以指定你要排序的主键是按升序还是按降序排列!ASC → 升序,DESC → 降序!
3.4 使用“Top”和“Max”
3.5 分页查询速度比较
说实话这些比较园子里面也很多,我就做个总结了,不实际测试了!
Top,Max > Row_Number > Top > 表变量 !
3.6 比较“Top Max”和“Row Number”的性能差异所在
如果对“SQL 执行计划”还没有一定的理解,请先看这篇文章:看懂SqlServer查询计划 ,值得一看的文章!
从上面的可以看出,在单表分页的情况下,“Row_Number”比“Top ,Max”会多检索出很多行,那么在性能上“Top Max”就比“Row_Number”好点!
Note:这种情况只限于单表操作的情况下,如果说是多表查询,感觉还是用“Row_Number”会比较好点,因为在多表的情况下,“Top,Max”或做出两次的连接查询,在大数据量的情况下,性能会比“Row_Number”差一点!如图:
4.大数据的分页思想
前几天看到一片文章是说关于百度,Google他们的分页思想,找不到那篇文章了,找到了园友发个链接给我!
我也是看到这些文章做个小总结,没什么创新!
5.思路很重要
我总觉得在编程之前应该就把思路理清楚,清楚之后就能行如流水,但是现在的我还没有到达这个境界,需要多多努力!
好了,差不多就是这么多了,也算对分页有了一点点的理解了,不至于以后工作需要而手忙脚乱的,写在这边与大家一起分享!