淺析ASP.NET高效分頁的實現(xiàn)過程
本文要實現(xiàn)的是以上一頁和下一頁的方式實現(xiàn)的ASP.NET高效分頁,至于以1、2、3、4這樣的形式顯示的ASP.NET高效分頁,還有待于作者的進一步研究ASP.NET高效分頁后實現(xiàn)。
簡單、高效這是我們追求的分頁效果。
現(xiàn)在有三種很常見的分頁:
1、分頁用的html和后臺代碼都自己寫 ,設(shè)計和代碼一般都只對應(yīng)某個網(wǎng)頁,難以在其他頁面很好的重用
2、最簡單的當(dāng)然是數(shù)據(jù)控件自帶的分頁功能,他的那些缺陷已經(jīng)被討論很多年了,我就不重復(fù)了,相信稍微有點魄力和職業(yè)態(tài)度的程序員都不會用那個分頁
3、自制的分頁控件,可以實現(xiàn)代碼和設(shè)計的分離,可以在多個頁面重用控件,但是缺陷是:每個頁面都得調(diào)用控件而且還要在頁面的后臺代碼里初始化控件,例如向控件里傳送總頁數(shù)、當(dāng)前分頁序號、頁面大小等
綜合以上分析,我打算自己做個簡單的分頁控件,思路如下:
1、首先必須實現(xiàn)分頁時代碼和設(shè)計的分離,例如“下一頁”,“上一頁”,他們的樣式寫在一個文件里,而把控制他們怎么顯示寫在另一個文件里,例如,到了最后一頁,“最后一頁”這個按鈕不能用。所以我寫了個template.html文件,這個描述了分頁時的樣式
- Code
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title></title>
- </head>
- <body>
- <div style="width: 100%; height: 30px; overflow: hidden; clear: both; font-size: 12px;" id="MyPagingString{10}">
- <div style="float: left; width: 50px; line-height: 20px; text-align: center; height: 20px;
- border: 1px solid #d8dfea; margin-left: 15px; cursor: pointer; display: {0}"
- onmouseover="p.on({1},this)" onmouseout="p.out({1},this)" onclick="p.direct({1},'first','{10}')">
- 第一頁
- </div>
- <div style="float: left; width: 50px; line-height: 20px; text-align: center; height: 20px;
- border: 1px solid #d8dfea; margin-left: 15px; cursor: pointer; display: {0}"
- onmouseover="p.on({2},this)" onmouseout="p.out({2},this)" onclick="p.direct({2},'previous','{10}')">
- 上一頁
- </div>
- <div style="float: left; width: 50px; line-height: 20px; text-align: center; height: 20px;
- border: 1px solid #d8dfea; margin-left: 15px; cursor: pointer; display: {0}"
- onmouseover="p.on({3},this)" onmouseout="p.out({3},this)" onclick="p.direct({3},'next','{10}')">
- 下一頁
- </div>
- <div style="float: left; width: 65px; line-height: 20px; text-align: center; height: 20px;
- border: 1px solid #d8dfea; margin-left: 15px; cursor: pointer; display: {0}"
- onmouseover="p.on({4},this)" onmouseout="p.out({4},this)" onclick="p.direct({4},'end','{10}',{11})">
- 最后一頁
- </div>
- <div style="float: left; height: 20px; line-height: 20px; margin-left: 20px; display: {9}">
- 每頁記錄:<span style=" color:Red;">{5}</span> 當(dāng)前頁: <span style=" color:red;">{6} </span> 總頁數(shù): <span style=" color:Red;">{7}</span> 總記錄數(shù): <span style=" color:Red;">{8}</span>
- </div>
- </div>
- <script type="text/javascript">
- var divTab='MyPagingString{10}';
- var div=[{1},{2},{3},{4}];
- var p = {
- init: function() {
- var pstr=document.getElementById(divTab).getElementsByTagName("div");
- if (!div[0]){
- pstr[0].style.color = '#ccc';}
- if (!div[1]){
- pstr[1].style.color = '#ccc';}
- if (!div[2]){
- pstr[2].style.color = '#ccc';}
- if (!div[3]){
- pstr[3].style.color = '#ccc';}
- },
- on: function(v, this_) {
- if (v) {
- this_.style.backgroundColor = '#3b5998'; this_.style.color = '#fff';
- }},
- out: function(v, this_) {
- if (v) {
- this_.style.backgroundColor = '#fff'; this_.style.color = '#000';
- }},
- direct:function(v,t,i){
- if (!v) {return;}
- var index=parseInt(i.split('|')[1]);
- var temp=i.split('|')[0]+'_paging_index=';
- var _cookie=document.cookie;
- var cookiekey=_cookie.substring(_cookie.indexOf(temp)+temp.length,_cookie.indexOf(";",_cookie.indexOf(temp)));
- document.cookie="paging_table="+i.split('|')[0];
- switch(t){
- case "first":
- document.cookie=temp+"0";
- break;
- case "previous":
- document.cookie=temp+(--index);
- break;
- case "next":
- document.cookie=temp+(++index);
- break;
- case "end":
- document.cookie=temp+arguments[3];
- break;
- }
- document.cookie="paging=1";
- document.forms[0].submit();
- }};
- p.init();
- </script>
- </body>
- </html>
當(dāng)程序第一次加載時,從硬盤讀取分頁模板文件template.html并且放入緩存,如果第二次有分頁請求時就從緩存讀取,
如果,template.html,被修改則再次從硬盤讀取,類似asp.net里的配置文件讀取機制,
緩存代碼如下:
- Code
- public static string GetPageHtml()
- {
- pagingHtml = (string)(HttpContext.Current.Cache["paging"]);
- if (string.IsNullOrEmpty(pagingHtml))
- {
- string path = null;
- CacheDependency cd;
- path = GetPagingTemplePath();
- cd = new CacheDependency(path);
- ReadPagingHtmlsFromDisk(path);
- HttpContext.Current.Cache.Insert("paging", pagingHtml, cd);
- }
- return pagingHtml;
- }
2、對數(shù)據(jù)源的獲取的sql實現(xiàn)了優(yōu)化,下面是兩種常用的分頁語句,第二條語句的優(yōu)勢在于:
not in 會引起全表掃描,而且不會使用聚集索引,而第二條語句沒有這樣的缺陷
- select top size * from table where id not in (select top index*size id from table )
- lect top size * from table where id > (select max (id) from (select top index*size id from table) as T )
對用戶輸入的sql語句,例如“select * from table”自動優(yōu)化成上面的第二種格式
下面這個方法實現(xiàn)了復(fù)雜sql語句轉(zhuǎn)化
- Code
- public static string AnalyticsSql(string sql, int index, int size)
- {
- string keyid = null, columns = null, table = null, orderby = null, wherestr = null, originalSql = null;
- originalSql = sql;
- originalSql = originalSql.Replace(originalSql.Substring(originalSql.IndexOf(" select ") + 8, originalSql.IndexOf(" from ") - 8 - originalSql.IndexOf(" select ")), " count(*) ");
- if (sql.IndexOf(" * ") != -1)
- {
- if (sql.IndexOf("|") != -1)
- {
- keyid = sql.Substring(sql.IndexOf("|") + 1, sql.IndexOf(" ", sql.IndexOf("|")) - sql.IndexOf("|") - 1);
- }
- else
- {
- keyid = "id";
- }
- columns = "*";
- }
- else
- {
- keyid = sql.Substring(sql.IndexOf("select") + 6, sql.IndexOf(",") - sql.IndexOf("select") - 6);
- columns = sql.Substring(sql.IndexOf("select") + 6, sql.IndexOf(" from ") - 6 - sql.IndexOf("select"));
- }
- if (sql.IndexOf(" where ") != -1)
- {
- wherestr = " where ";
- if (sql.IndexOf(" order ") != -1)
- wherestr += sql.Substring(sql.IndexOf(" where ") + 7, sql.IndexOf(" order ") - sql.IndexOf(" where ") - 7);
- else
- wherestr += sql.Substring(sql.IndexOf(" where ") + 7);
- }
- table = GetSqlTable(sql);
- if (sql.IndexOf(" order ") != -1)
- {
- orderby = sql.Substring(sql.LastIndexOf("by") + 2);
- }
- else
- {
- orderby = keyid;
- }
- sql = "select top " + size.ToString() + " " + columns + " from " + table + " where " + keyid + ">isnull((select max (" + keyid + ") from (select top " + (index * size).ToString() + " " + keyid.ToString() + " from " + table + wherestr + " order by " + orderby + ") as T),0) order by " + keyid;
- return originalSql + ";" + sql;
- }
需要補充的是分頁排序時id問題:
如果你的SQL語句寫成了這樣:
- 1、select * from table where ... order ...
- 則優(yōu)化后的sql以id排序
- 2、select *|CustomerId from table where ... order ...
- 則優(yōu)化后的sql以CustomerId排序
- 2、select CustomerId,CustomerName,... from table where ... order ...
- 則優(yōu)化后的sql以CustomerId排序
- ==================================
然后根據(jù)當(dāng)前信息格式化分頁顯示的htmls,例如,頁數(shù)、頁號、總記錄數(shù)、以及上下頁按鈕是否可用。具體代碼:
- Code
- public static string AnalyticsPagingHtmls(string tableAndindex,int count, int size, int index)
- {
- string _GetPageHtml = GetPageHtml();
- return string.Format
- (
- _GetPageHtml.Substring(0, _GetPageHtml.IndexOf(",{4}];") + 6),
- count == 0 || count <= size ? "none" : "",
- index == 0 ? "0" : "1",
- index == 0 ? "0" : "1",
- (index + 1 == ((count % size) == 0 ? count / size : ((count / size) + 1))) ? "0" : "1",
- (index + 1 == ((count % size) == 0 ? count / size : ((count / size) + 1))) ? "0" : "1",
- size,
- index + 1,
- (count % size) == 0 ? count / size : (count / size) + 1,
- count,
- count == 0 ? "none" : "",
- tableAndindex,
- ((count % size) == 0 ? count / size : ((count / size) + 1))-1
- )
- + _GetPageHtml.Substring(_GetPageHtml.IndexOf(",{4}];") + 6);
- }
如何使用這個分頁方法:
第一步:在配置文件里寫下如下代碼:
- Code
- <configSections>
- <section name="MyPaging" type="System.Configuration.NameValueSectionHandler"/>
- </configSections>
- <MyPaging>
- <add key="Paging" value="~/Paging/template.htm"/>
- </MyPaging>
第二步:在cs文件里,直接調(diào)用就行
- protected void Page_Load(object sender, EventArgs e)
- {
- if(MyPaging.IsPaging)
- {
- p1.InnerHtml = MyPaging.ExecutePaging(MyRep, "select CustomerId,ShipName,ShipAddress,ShippedDate from orders ", 0,5);
- p2.InnerHtml = MyPaging.ExecutePaging(MyRep2, "select CustomerID,CompanyName,ContactName,Address from dbo.Customers", 0,5);
- }
- }
前臺代碼:
- Code
- <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head runat="server">
- <title></title>
- </head>
- <body>
- <form id="form1" runat="server">
- <asp:Repeater ID="MyRep" runat=server>
- <ItemTemplate>
- <div style="width:100%; height:20px;">
- <%# Eval("CustomerID") %>
- <%# Eval("ShipName") %>
- <%# Eval("ShipAddress") %>
- <%# Eval("ShippedDate")%>
- </div>
- </ItemTemplate>
- </asp:Repeater>
- <div id="p1" runat=server></div>
- <asp:Repeater ID="MyRep2" runat=server>
- <ItemTemplate>
- <div style="width:100%; height:20px;">
- <%# Eval("CustomerID")%>
- <%# Eval("CompanyName")%>
- <%# Eval("ContactName")%>
- <%# Eval("Address")%>
- </div>
- </ItemTemplate>
- </asp:Repeater>
- <div id="p2" runat=server></div>
- </form>
- </body>
- </html>
實現(xiàn)效果:
原文標題:asp.net簡單&高效的分頁實現(xiàn),請大家提提意見
鏈接:http://www.cnblogs.com/chenxumi/archive/2009/11/05/1596777.html