最近在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
此时真分页就实现了,是不是特别简单。当您看到这里,相信您一定会使用真分页了。