web页面一次一般显示10行数据为好,但往往很多时候我们从数据库中查出来上万条数据,这个时候我们要在上万条数据中显示10条,那就必须分页。分页的第一问题就是分页数据。
分页数据
分页的数据分为两种,一种是在数据库中只取需要的10条数据,这也是性能提升的标致,一种是全盘拖出,放到程序缓存中再用程序来分页。
第一种取数据方式:
01.select top [PageSize] * from [Table] where id not in( select top [CurrentPage-1] [PageSize] id from [Table] )
用于access,mssql当中,另一种是存储过程,这也是最快的取数据方式
01.ALTER PROCEDURE GetAuthors
02. @PageIndex int,
03. @PageSize int
04.AS
05.BEGIN
06. -- Set the page bounds
07. DECLARE @PageLowerBound int
08. DECLARE @PageUpperBound int
09. DECLARE @TotalRecords int
10. SET @PageLowerBound = @PageSize * (@PageIndex-1)
11. SET @PageUpperBound = @PageSize*@PageIndex-1
12.
13. -- Create a temp table TO store the select results
14. CREATE TABLE #PageIndexForAuthors
15. (
16. IndexId int IDENTITY (0, 1) NOT NULL,
17. au_id varchar(11),
18. au_lname varchar(40),
19. au_fname varchar(20),
20. phone char(12),
21. address varchar(40),
22. city varchar(20),
23. state char(2),
24. zip char(5),
25. contract bit
26. )
27.
28. -- Insert into our temp table
29. INSERT INTO #PageIndexForAuthors
30. (au_id ,au_lname,au_fname,phone,address,city,state,zip,contract)
31. SELECT *
32. FROM authors
33. ORDER BY au_id
34.
35. SELECT @TotalRecords = @@ROWCOUNT
36.
37. SELECT * FROM #PageIndexForAuthors
38. WHERE IndexId between @PageLowerBound AND @PageUpperBound
39. ORDER BY au_id
40. RETURN @TotalRecords
41.END
42.GO
上面这段存储过程是仿微软的写法,微软在Membership里面采用也是这存储过程分页。
其他数据库取数据也有不同,sql2005有行号函数,oracle也有,mysql就更好取了limit 10,20
第二种就是全部数据取出来再做缓存,数据用程序处理,.ado/jdbc有定位法,Adapter.Fill()用这个填充需要的数据,GridView自定义分页事件就是使用这个,看到很多自定义控件也使用这种方式。
分页采取何种方式
现在网页都讲究Seo,所以在前台分页的时候我摒弃PostBack方式,而采用URL方式.不采PostBack也就不需要用到ViewState[“PageNo”]存取数据,每次分页的时候都重新加载,所以视图状态就没撒用.
好了,现在很清楚,为了效率,为了SEO,混口饭吃真不容易,数据采用存储过程从数据库中取所需的数据,并返回总共条数.分页采用URL方式,一是为了urlRewrite和seo,至于postback提倡在后台分页,毕竟方便。
那现在就到了实现阶段,数据显示控件肯定是Repeater/DataList/GridView统杀.刚开始我是想把分页控件和数据显示在一起,但是若使用存储过程传递参数比较麻烦,不使的存储过程参数个数是不一样的,所以决定采用数据显示和分页控件分离的方法,分页控件只传递总记录数就可以了.
所以即想当爹又当妈,那是很累的,现在主要使用存储过程从数据库取出所需的数据,分页控件又采用URL,到止分页效率高了,SEO也实现了,但是三层架构中不好使,三层架构中要传参中加页码也可以使。
这是页面代码:
01.public partial class PagerDemo : System.Web.UI.Page
02.{
03. private int TotalRecords;
04. protected void Page_Load(object sender, EventArgs e)
05. {
06. Repeater1.DataSource = GetTable();
07. Repeater1.DataBind();
08. Pager1.TotalRecords = TotalRecords ;
09. }
10. private DataTable GetTable()
11. {
12. string connStr = ConfigurationManager.ConnectionStrings["pubsConnectionString"].ConnectionString;
13. DataTable dt = new DataTable();
14. using (SqlConnection conn = new SqlConnection(connStr))
15. {
16. SqlParameter[] prms = new SqlParameter[3];
17. prms[0] = new SqlParameter("@PageIndex", SqlDbType.Int);
18. prms[0].Value = Pager1.PageIndex;
19. prms[1] = new SqlParameter("@PageSize", SqlDbType.Int);
20. prms[1].Value = Pager1.PageSize;
21. prms[2] = new SqlParameter("@TotalRecords", SqlDbType.Int);
22. prms[2].Direction = ParameterDirection.ReturnValue;
23. SqlCommand cmd = conn.CreateCommand();
24. cmd.Parameters.AddRange(prms);
25. cmd.CommandType = CommandType.StoredProcedure;
26. cmd.CommandText = "GetAuthors";
27. SqlDataAdapter Adapter = new SqlDataAdapter();
28. Adapter.SelectCommand = cmd;
29. try
30. {
31. conn.Open();
32. Adapter.Fill(dt);
33. TotalRecords = int.Parse(cmd.Parameters["@TotalRecords"].Value.ToString());
34. return dt;
35. }
36. catch (Exception ex)
37. {
38. throw ex;
39. }
40. }
41. }
42.}
这是用户控件代码:
01.public partial class Pager : System.Web.UI.UserControl
02.{
03. private int _totalRecords;
04. private int _pageSize = 10;
05. private int _maxPagesShown = 10;
06.
07. private System.Collections.Generic.List<string> queryString;
08. protected void Page_Load(object sender, EventArgs e)
09. {
10. SetPages();
11. }
12. public int TotalRecords
13. {
14. get { return _totalRecords; }
15. set { _totalRecords = value; }
16. }
17. public int PageIndex
18. {
19. get
20. {
21. return Request.QueryString["PageNo"] == null ? 1 : int.Parse(Request.QueryString["PageNo"]);
22. }
23. }
24. public int PageSize
25. {
26. get { return _pageSize; }
27. set { _pageSize = value; }
28. }
29. public int MaxPagesShown
30. {
31. set { _maxPagesShown = value; }
32. }
33. public int PageCount
34. {
35. get { return TotalRecords / PageSize + 1; }
36. }
37.
38. private void SetPages()
39. {
40. Panel1.Controls.Clear();
41. HyperLink link;
42. if (PageIndex - _maxPagesShown > 1)
43. {
44. link = new HyperLink();
45. link.Text = "<<";
46. link.NavigateUrl = MakeLink("1");
47. Panel1.Controls.Add(link);
48. }
49. if (PageIndex > 1)
50. {
51. link = new HyperLink(); link.Text = "<";
52. link.NavigateUrl = MakeLink(PageIndex - 1);
53. Panel1.Controls.Add(link);
54. }
55. for (int i = PageIndex - _maxPagesShown; i <= PageIndex + _maxPagesShown; i++)
56. {
57. if (i > 0 && i <= PageCount)
58. {
59. if (PageIndex == i)
60. {
61. link = new HyperLink();
62. link.Text = "Page " + i.ToString();
63. link.CssClass = "selected"; Panel1.Controls.Add(link);
64. }
65. else
66. {
67. link = new HyperLink(); link.Text = i.ToString();
link.NavigateUrl = MakeLink(i);
Panel1.Controls.Add(link);
68. }
69. }
70. }
71.
72. if (PageIndex < PageCount)
73. {
74. link = new HyperLink(); link.Text = ">";
link.NavigateUrl = MakeLink(PageIndex + 1);
Panel1.Controls.Add(link);
75. }
76. if (PageIndex + _maxPagesShown < PageCount)
77. {
78. link = new HyperLink(); link.Text = ">>";
link.NavigateUrl = MakeLink(PageCount);
Panel1.Controls.Add(link);
79. }
80. }
81. private string MakeLink(Object pageID)
82. {
83. string currentPageID = pageID.ToString();
84. queryString = new System.Collections.Generic.List<string>();
85. foreach (string key in Request.QueryString.Keys)
86. {
87. if (key != "PageNo")
88. {
89. queryString.Add(key + "=" + Request.QueryString[key]);
90. }
91. }
92. queryString.Add("PageNo=" + pageID.ToString());
93. string filePath = Request.CurrentExecutionFilePath;
94. return String.Format(filePath + "?{0}", String.Join("&", queryString.ToArray()));
95. }
96.}