最近在web界面的時候,遇到了一些非常現實的問題。最讓人頭疼的問題就是顯示數據中的書畫作品。這些書畫作品都會以圖片的形式展示給用戶。
起初做的時候並沒有想太多,只按着最簡單的方式將所有的圖片從數據庫中查出來並顯示在界面中,做完界面之後,自己在數據庫中添加了一些數據做測試,發現每次打開網頁都很慢。由於原來看視頻的時候就知道真假分頁,但是當時對於分頁並沒有深刻的體會,不知道真假分頁的優缺點。由於每次打開網頁都很慢,讓我一下想起來了分頁這件事。
面對幾十條的數據,網頁都會顯示特別慢,如果面對上千上萬條的記錄時,網頁就不知道慢成什麼樣子了,此時系統就可以說報廢了。今天我們從本質上將分頁問題解決掉。
分頁
分頁是將所有的內容分成不同的頁面,它是常用的導航技術,在web開發中都會涉及到。分頁分爲真分頁和假分頁兩種。
假分頁
從數據庫一次性取出所有數據綁定到控件上,再將所有數據根據每頁顯示多少條記錄而分頁。例子:
前臺頁面代碼:
- <p style="height: 23px; width:700px; text-align: center;font-size:16px;" background="images/相冊_09.jpg">
- 當前頁碼爲[<asp:Label ID="lblCurrentPage" runat="server" Text="1"></asp:Label>]頁 總頁碼[<asp:Label
- ID="lblSumPage" runat="server" Text="0"></asp:Label>]頁
- <asp:LinkButton ID="lnkBtnFirst" runat="server" Font-Underline="False" OnClick="lnkBtnFirst_Click"> 第一頁 </asp:LinkButton>
- <asp:LinkButton ID="lnkBtnPrevious" runat="server" Font-Underline="False" OnClick="lnkBtnPrevious_Click"> 上一頁 </asp:LinkButton>
- <asp:LinkButton ID="lnkBtnNext" runat="server" Font-Underline="False" OnClick="lnkBtnNext_Click"> 下一頁 </asp:LinkButton>
- <asp:LinkButton ID="lnkBtnLast" runat="server" Font-Underline="False" OnClick="lnkBtnLast_Click"> 末一頁 </asp:LinkButton>
- </p>
後臺代碼:
- protected void Page_Load(object sender, EventArgs e)
- {
- //如果用戶沒有登錄,則跳轉到首頁
- if (Session["UserName"] != null)
- {
- DataListBind();
- }
- else
- {
- Response.Redirect("default.aspx");
- }
- }
- ///// <summary>
- ///// 綁定當前用戶的照片
- ///// </summary>
- public void DataListBind()
- {
- //判斷用戶是否已經登錄
- if (Session["UserID"] == null)
- {
- Page.ClientScript.RegisterStartupScript(Page.GetType(), "message", "<script language='javascript' defer>alert('您尚未登錄,請登錄!');</script>");
- return;
- }
- DataTable dt = new DataTable();
- dt.Columns.Add(new DataColumn("PhotoID", typeof(string)));
- dt.Columns.Add(new DataColumn("PhotoName", typeof(string)));
- dt.Columns.Add(new DataColumn("PhotoUrl", typeof(string)));
- dt.PrimaryKey = new[] { dt.Columns["PhotoID"] };
- //實例化一個B層對象
- userPhotoBLL userphotobll = new userPhotoBLL();
- //實例化一個實體的對象
- userPhotoEntity enUserPhoto = new userPhotoEntity();
- enUserPhoto.UserID = Session["UserID"].ToString();//獲取當前用戶的ID
- string strWhere = "UserID='" + enUserPhoto.UserID + "'";
- //根據查詢條件獲得數據列表
- DataSet ds = userphotobll.GetList(strWhere);
- //如果沒有記錄,則顯示一張空照片
- if (ds.Tables[0].Rows.Count == 0)
- {
- NoImage.Visible = true;
- }
- else {
- NoImage.Visible = false;
- }
- for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
- {
- if (ds.Tables[0].Rows.Count > 0)
- {
- DataRow dr = dt.NewRow();
- dr[0] = ds.Tables[0].Rows[i][1].ToString();
- dr[1] = ds.Tables[0].Rows[i][2].ToString();
- dr[2] = ds.Tables[0].Rows[i][5].ToString();
- dt.Rows.Add(dr);
- }
- }
- PagedDataSource pds = new PagedDataSource();
- pds.DataSource = dt.DefaultView; //將查詢結果綁定到分頁數據源上。
- pds.AllowPaging = true; //允許分頁
- pds.PageSize = 12; //設置每頁顯示多少張圖片
- pds.CurrentPageIndex = Convert.ToInt32(lblCurrentPage.Text) - 1; //設置當前頁
- lnkBtnFirst.Enabled = true; //控件翻頁控件都設置爲可用
- lnkBtnLast.Enabled = true;
- lnkBtnNext.Enabled = true;
- lnkBtnPrevious.Enabled = true;
- if (lblCurrentPage.Text == "1") //如果當前顯示第一頁,“第一頁”和“上一頁”按鈕不可用。
- {
- lnkBtnPrevious.Enabled = false;
- lnkBtnFirst.Enabled = false;
- }
- if (lblCurrentPage.Text == pds.PageCount.ToString()) //如果顯示最後一頁,“末一頁”和“下一頁”按鈕不可用。
- {
- lnkBtnNext.Enabled = false;
- lnkBtnLast.Enabled = false;
- }
- lblSumPage.Text = pds.PageCount.ToString(); //實現總頁數
- //將分頁結果綁定到DataList控件上
- dlPictrue.DataSource = pds; //綁定數據源
- dlPictrue.DataKeyField = "PhotoID";
- dlPictrue.DataBind();
- }
- /// <summary>
- /// 第一頁
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- protected void lnkBtnFirst_Click(object sender, EventArgs e)
- {
- lblCurrentPage.Text = "1";
- DataListBind();
- }
- /// <summary>
- /// 前一頁
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- protected void lnkBtnPrevious_Click(object sender, EventArgs e)
- {
- lblCurrentPage.Text = (Convert.ToInt32(lblCurrentPage.Text) - 1).ToString();
- DataListBind();
- }
- /// <summary>
- /// 下一頁
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- protected void lnkBtnNext_Click(object sender, EventArgs e)
- {
- lblCurrentPage.Text = (Convert.ToInt32(lblCurrentPage.Text) + 1).ToString();
- DataListBind();
- }
- /// <summary>
- /// 最後一頁
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- protected void lnkBtnLast_Click(object sender, EventArgs e)
- {
- lblCurrentPage.Text = lblSumPage.Text;
- DataListBind();
- }
調用D層的方法,將返回的數據表直接綁定到控件上。
真分頁
控件上每一頁需要顯示多少數據,就從數據庫取出並綁定多少數據,每次換頁時都需要訪問數據庫。在網頁設計中一定避免不了使用分頁,並且在平時我們都經常使用,例如百度,你每次查看下一頁的圖片時,都會出現正在加載的字樣。這樣的例子特別多,我想說的是這就是真分頁的效果。
在我的項目中我使用的是aspnetpager分頁控件,這個控件使用起來相對要簡單很多。aspnetpager的實現效果如圖:
前臺的代碼:
- <webdiyer:AspNetPager ID="anp" runat="server" FirstPageText="首頁" LastPageText="尾頁"
- NextPageText="下一頁" onpagechanged="anp_PageChanged" PageSize="12"
- PrevPageText="上一頁"
- CustomInfoHTML="總共%RecordCount%條記錄,共%PageCount%頁"
- ShowCustomInfoSection="Left" ShowPageIndexBox="Never"
- CssClass="paginator" CurrentPageButtonClass="cpb" AlwaysShow="True"
- CustomInfoSectionWidth="">
- </webdiyer:AspNetPager>
- protected static PagedDataSource pds = new PagedDataSource();//創建一個分頁數據源的對象且一定要聲明爲靜態
- paintingBLL paintingbll = new paintingBLL();
- protected void Page_Load(object sender, EventArgs e)
- {
- if (!Page.IsPostBack)
- {
- //第一次進入該頁面時
- //加載所有的書畫作品
- string strWhereRecord = "";
- //獲得數據總數
- anp.RecordCount = paintingbll.GetRecordCount(strWhereRecord);
- //調用綁定的方法
- BindGV();
- //加載所有的最新訂單
- //賦值
- string strWhere = "DoSign='成交'";
- string filedOrder = "DealTime";
- //綁定數據源
- gvPaintOrder.DataSource = new OrderFormBLL().GetList(10, strWhere, filedOrder);
- gvPaintOrder.DataBind();
- }
- }
- //分頁事件
- protected void anp_PageChanged(object sender, EventArgs e)
- {
- BindGV();
- }
- //綁定書畫
- protected void BindGV()
- {
- string strWhere="";
- string orderby="";
- //頁大小
- int pagesize = anp.PageSize;
- //頁索引
- int pageindex = anp.CurrentPageIndex;
- //實例化一個B層對象
- paintingBLL paintingbll = new paintingBLL();
- //獲得所有的書畫數據,開始索引值 (pageindex - 1) * pagesize + 1,結束索引值:pagesize * pageindex
- DataSet ds = paintingbll.GetListByPage(strWhere, orderby, (pageindex - 1) * pagesize + 1, pagesize * pageindex);
- //如果沒有記錄,則顯示沒有條
- if (ds.Tables[0].Rows.Count == 0)
- {
- NoImage.Visible = true;
- }
- else
- {
- NoImage.Visible = false;
- }
- pds.DataSource = ds.Tables[0].DefaultView;//把數據集中的數據放入分頁數據源中
- dlPictrue.DataSource = pds;//綁定Datalist
- dlPictrue.DataBind();
- }
- /// <summary>
- /// 獲取記錄總數
- /// </summary>
- public int GetRecordCount(string strWhere)
- {
- StringBuilder strSql=new StringBuilder();
- strSql.Append("select count(1) FROM V_PaintingInfo ");
- if(strWhere.Trim()!="")
- {
- strSql.Append(" where "+strWhere);
- }
- object obj = DbHelperSQL.GetSingle(strSql.ToString());
- if (obj == null)
- {
- return 0;
- }
- else
- {
- return Convert.ToInt32(obj);
- }
- }
- /// <summary>
- /// 分頁獲取數據列表
- /// </summary>
- public DataSet GetListByPage(string strWhere, string orderby, int startIndex, int endIndex)
- {
- StringBuilder strSql=new StringBuilder();
- strSql.Append("SELECT * FROM ( ");
- strSql.Append(" SELECT ROW_NUMBER() OVER (");
- if (!string.IsNullOrEmpty(orderby.Trim()))
- {
- strSql.Append("order by T." + orderby );
- }
- else
- {
- strSql.Append("order by T.PaintingID ASC");
- }
- strSql.Append(")AS Row, T.* from V_paintingInfo T ");
- if (!string.IsNullOrEmpty(strWhere.Trim()))
- {
- strSql.Append(" WHERE " + strWhere);
- }
- strSql.Append(" ) TT");
- strSql.AppendFormat(" WHERE TT.Row between {0} and {1}", startIndex, endIndex);
- return DbHelperSQL.Query(strSql.ToString());
- }
真假對決
從以上兩者的名字我們可以看出,邪不壓正,真的永遠都不可能成爲假的。優缺點:
二者其實各有各的優缺點,可根據需要來選擇。(比如數據量較多時,用真分頁;想減少與後臺的交互,可以使用假分頁)。假分頁,如果數據量較多,在首次頁面加載的時候會比較慢,嚴重影響用戶體驗,Web開發和搜索引擎優化。真分頁的效率無疑是最高的,它還有很多的優點:
1.每次點擊下一頁,客戶端訪問服務器的時間基本一樣,提高用戶體驗,更加的人性化。
2.對於大數據量可以從容的面對。
缺點:與後臺的交互次數增多。
本質區別:
本質區別在於分頁時從數據庫讀取信息的方式:假分頁:一次性讀取數據;真分頁:多次讀取數據。真分頁主要實現在於sql語句上:
SELECT * FROM (SELECT ROW_NUMBER() OVER ( order by T.ArtistID ASC)AS Row, T.* from 表名(視圖名) T ) TT WHERE TT.Row between 開始索引值 and 結束索引值
注意:
1.使用aspnetpager,首先要查詢出總記錄數來計算總頁數RecordCount,如上代碼,再將需要的數據查出來將返回的數據表直接綁定到repeater控件、dataList控件和gridView控件上。
2.使用AspNetPager時一定將它附加到vs的.net組件中,纔可以使用。
aspnetpager下載:http://download.csdn.net/detail/jiuqiyuliang/6837175
此時真分頁就實現了,是不是特別簡單。當您看到這裏,相信您一定會使用真分頁了。