GridView+存储过程实现'真分页'

11 篇文章 0 订阅

  GridView,ASP.NET中的表格控件,和Repeater控件一样,在ASP.NET中都是很常用的两个表格控件,GridView自己也有分页功能,实现是将一张表的数据全部绑定到GridView,然后再进行分页,这就是通常我们所说的'假分页'。在应对小数据量上完全没问题,但问题往往没有那么简单,在面对大数据量的问题上,GridView自己的分页还是力不从心,严重影响效率,用户体验也不好。

  要解决这个问题,实现'真分页',就要从根上去分析,为什么'假分页'速度慢,因为它一次获取的是整张表的数据,但是最后显示的只是一页,所以,如果我们只查询需要显示的一页数据(上页下页,首页尾页,跳页都只查询需要的一页数据),在绑定到GridView中,查询分页的速度会快很多,这就是所谓的'真分页'了。剩下的问题就是SQL语句去实现了。经过一番查询研究,通过存储过程实现真分页效果挺好。


存储过程


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[PROC_GridViewPage]
	--@TableList Varchar(200), --查询的字段,用逗号隔开
	@TableName Varchar(30),   --查询的表名
	--@SelectWhere Varchar(500),--查询的条件
	@SelectOrderId Varchar(20), --表主键字段名
	@SelectOrder Varchar(200),  --排序,order by 列名
	@intPageNo int,       --页号
	@intPageSize int,           --每页显示数
	@RecordCount int OUTPUT     --总记录数(OUTPUT表示是存储过程输出型参数,接收方法见DAL层)
AS
	declare @TmpSelect      NVarchar(600)  --声明变量

	 set nocount on    --关闭计数
 	 --获取表中记录总数
	 set @TmpSelect = 'select @RecordCount = count(*) from '+@TableName+' '         --可以添加查询条件+@SelectWhere

	execute sp_executesql
 	@TmpSelect,    --执行上面的sql语句
 	N'@RecordCount int OUTPUT' ,   --执行输出数据的sql语句,output出总记录数
 	@RecordCount  OUTPUT

	if (@RecordCount = 0)    --如果表中没有,则返回0
        return 0
	      
	/*判断页数是否正确*/
	if (@intPageNo - 1) * @intPageSize > @RecordCount   --页号大于总页数,返回错误
	    return (-1)
	set nocount off--打开计数
	
BEGIN
	set @TmpSelect = 'select top '+str(@intPageSize)+' '+ '*' +' from '+@TableName+' where '+@SelectOrderId+' not in(select top '+str((@intPageNo-1)*@intPageSize)+' '+@SelectOrderId+' from '+@TableName+' '+@SelectOrder+') '+@SelectOrder
END
	execute sp_executesql @TmpSelect
	return(@@rowcount)
GO



  sp_executesql?和EXEC一样在存储过程中执行sql语句的命令,平时我们见到和使用的通常是EXEC,sp_executesql的不同之出在于,它提供了一个借口,支持参数的输入和输出,灵活性更好,而且sp_executesql的执行性能更好。还没有深入研究sp_executesql,既然都说比EXEC好,那就先用吧。


.NET代码实现


前台代码

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="List.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>GridView分页</title>
	</head>
	<body>
	     <form id="form1" runat="server">
			<div>
 				<asp:GridView ID="gridView" runat="server" AllowPaging="True" Width="100%" CellPadding="3"
				         OnPageIndexChanging="gridView_PageIndexChanging" BorderWidth="1px" DataKeyNames="ID"
				         OnRowDataBound="gridView_RowDataBound" AutoGenerateColumns="false"
				         RowStyle-HorizontalAlign="Center" OnRowCreated="gridView_OnRowCreated" EmptyDataText="没有您查找的数据"
				         ShowHeaderWhenEmpty="True" PageSize="20" >
 					<Columns>
 						<asp:BoundField DataField="name" HeaderText="姓名" SortExpression="name" ItemStyle-HorizontalAlign="Center">
						 <asp:BoundField DataField="sex" HeaderText="性别" SortExpression="sex" ItemStyle-HorizontalAlign="Center">
 						</asp:BoundField>
						 <asp:BoundField DataField="idNumber" HeaderText="身份证号" SortExpression="idNumber"
						                 ItemStyle-HorizontalAlign="Center">
 						</asp:BoundField>
					 </Columns>
				</asp:GridView>
			</div>		
			<asp:HyperLink ID="pagefirst" runat="server">首页</asp:HyperLink>
    			<asp:HyperLink ID="pageup" runat="server">上一页</asp:HyperLink>
 			<asp:HyperLink ID="pagedown" runat="server">下一页</asp:HyperLink>
			<asp:HyperLink ID="pageend" runat="server">尾页</asp:HyperLink>
			 第<asp:Label ID="lbRow" runat="server" Text="Label"></asp:Label>页,
			 共<asp:Label ID="lbpage" runat="server" Text="Label"></asp:Label>页,
			 共<asp:Label ID="lbRecord" runat="server" Text="Label"></asp:Label>条记录,
			 转到<asp:TextBox ID="txtlink" runat="server" Width="29px"></asp:TextBox>页 
			 <asp:LinkButton ID="link" runat="server" OnClick="link_Click" TabIndex="1">转到</asp:LinkButton>	    
 		</form>
 	</body>
</html>



后台代码


实体类 GridViewPageEntity.cs

这个实体类的作用是定义了存储过程中的变量:字段,表名,查询条件,主键,排序方式,页号,总记录数

public partial class GridViewPageEntity
    {
        public GridViewPageEntity()
		{}
        ///定义属性中的变量
        /// <summary>
        /// 字段,表名,查询条件,主键,排序方式,页号,总记录数
        /// </summary>
        private string _Fields;
        private string _TableName;
        private string _SelectWhere;
        private string _Primarykey;
        private string _OrderBy;
        private int _intPageNo;
        private int _intPageSize;
        private int _RecordCount;

        //属性
        public string Fields
        {
            set { _Fields = value; }
            get { return _Fields; }
        }
        public string TableName
        {
            set { _TableName = value; }
            get { return _TableName; }
        }
        public string SelectWhere
        {
            set { _SelectWhere = value; }
            get { return _SelectWhere; }
        }
        public string Primarykey
        {
            set { _Primarykey = value; }
            get { return _Primarykey; }
        }
        public string OrderBy
        {
            set { _OrderBy = value; }
            get { return _OrderBy; }
        }
        public int intPageNo
        {
            set { _intPageNo = value; }
            get { return _intPageNo; }
        }
        public int intPageSize
        {
            set { _intPageSize = value; }
            get { return _intPageSize; }
        }
        public int RecordCount
        {
            set { _RecordCount = value; }
            get { return _RecordCount; }
        }
    }


界面层

        protected void Page_Load(object sender, EventArgs e)
       {
	   if (!Page.IsPostBack)       //判断是否第一次加载页面
          {
  		BindData();
	   }
        }

        #region 数据绑定
        public void BindData()
        {
	    private readonly GridViewPageBLL gridViewPageBll = new GridViewPageBLL(); //实例化GridViewPageBLL 业务逻辑类
            PersonalFiles.Entity.GridViewPageEntity gridViewEntity = new Entity.GridViewPageEntity();//实例化GridViewPageEntity实体类
            gridViewEntity.intPageNo = 1;     //起始页号
            gridViewEntity.intPageSize = 20;  //每页显示行数
            gridViewEntity.TableName = "V_XINMainTecnce"; //查询的表名(这里用的视图)
            gridViewEntity.Primarykey = "pri";            //主键
            gridViewEntity.OrderBy = "order by ID";       //排序方式
            //获取当前页号,判断是否获取页,没有则页号为起始页          
            if (Request.QueryString["CurrentPage"] == null)
            {
                gridViewEntity.intPageNo = 1;
            }
            else
            {
                gridViewEntity.intPageNo = Int32.Parse(Request.QueryString["CurrentPage"]);
            }

            int sumPage;  //定义总页数
            int pageNo = gridViewEntity.intPageNo;     //当前页数
            int pageSize = gridViewEntity.intPageSize; //每页显示行数

            DataTable dt = new DataTable();               //实例化DataTable 
            dt = gridViewPageBll.GetList(gridViewEntity); //获取数据列表        
            gridView.DataSource = dt;                     //绑定数据
            gridView.DataBind();
            string allcount = dt.Rows[0]["allcount"].ToString();  //获取表中数据总行数
            Int32 RecordCount = int.Parse(allcount);             //求出总记录数,该值是output出来的值
            Int32 RowCount = (Int32)dt.Rows.Count;               //求出当前页中的记录数,在最后一页不等于pagesize,

            lbRecord.Text = RecordCount.ToString();    //显示总条数
            lbRow.Text = pageNo.ToString();            //显示当前页数
            sumPage = (Int32)RecordCount / pageSize;   //计算总页数
            if (RecordCount % pageSize > 0)     //判断总行数是否大于每页行数,是则总页数自加1
            {
                sumPage = sumPage + 1;

            }
            lbpage.Text = sumPage.ToString();         //显示总页数
            if (pageNo > 1)           //判断当前页是否大于1(不是首页),判断是否可以进行首页和上一页
            {
                pagefirst.NavigateUrl ="List.aspx?CurrentPage=1";   //链接首页
                pageup.NavigateUrl =string.Concat("List.aspx?CurrentPage=", "", pageNo - 1); //上一页操作
            }
            else
            {
                pageup.NavigateUrl ="";
                pagefirst.NavigateUrl ="";
            }
            if (pageNo < sumPage)   //判断当前页是否小于总页数,判断是否可以进行下一页和最后一页
            {
                pageend.NavigateUrl =string.Concat("List.aspx?CurrentPage=", "", sumPage);  //最后一页操作
                pagenext.NavigateUrl =string.Concat("List.aspx?CurrentPage=", "", pageNo + 1); //下一页操作
            }
            else
            {
                pagenext.NavigateUrl ="";
                pageend.NavigateUrl ="";
            }
        }
        #endregion
 


业务逻辑类BLL.GridViewPageBLL

	/// <summary>
	/// GridView分页 逻辑类
	/// </summary>
	public partial class GridViewPageBLL
	{
		 private readonly MainTenanceDAL gridViewPageDal=new GridViewPageDAL();

                /// <summary>
	        /// 获取数据BLL方法
	        /// </summary>
	        /// <param name="gridViewEntity">分页参数实体</param>
	        /// <returns>返回DataTable</returns>

                public DataTable GetList(PersonalFiles.Entity.GridViewPageEntity gridViewEntity) 
                { 
                      return gridViewPageDal.GetList(gridViewEntity); 
                 }
           }



数据访问类DAL.GridViewDAL

        /// <summary>
        /// 查询数据DAL方法
        /// </summary>
        /// <param name="gridViewEntity"></param>
        /// <returns></returns>
        public DataTable GetList(PersonalFiles.Entity.GridViewPageEntity gridViewEntity)
        {
           
         //存储过程
            string strSql = "PROC_GridViewPage";
            //添加赋值参数
            SqlParameter[] paras = new SqlParameter[] { 
               //new SqlParameter("@TableList","ID"), 
               new SqlParameter("@TableName",gridViewEntity.TableName),
               new SqlParameter ("@SelectOrderId",gridViewEntity.Primarykey),
               new SqlParameter ("@SelectOrder",gridViewEntity.OrderBy),
               new SqlParameter ("@intPageNo",gridViewEntity.intPageNo),
               new SqlParameter ("@intPageSize",gridViewEntity.intPageSize),
               new SqlParameter ("@RecordCount",SqlDbType.Int),
               new SqlParameter ("RowCount", SqlDbType.Int)
            };
            //获取表中总数据量,如果不需要界面显示可以不用获取。
            paras[5].Direction = ParameterDirection.Output;
            //获取查询的一页的数据量,我们在界面层给@intPageSize赋的值是20,所以这里返回来的也是20
            paras[6].Direction = ParameterDirection.ReturnValue;
            DataSet ds = new DataSet();
            //执行带参数的查询存储过程
            DataTable dt = DbHelperSQL.ExecuteQuery(strSql,paras,CommandType.StoredProcedure);
            string allcount = paras[5].Value.ToString(); 
            string count = paras[6].Value.ToString();
            //存储表总数据量,如果不需要界面显示可以不用获取。
            dt.Columns.Add("allcount", typeof(string));
            dt.Rows[0]["allcount"] = allcount; 
            //返回查询结果(datatable)
            return dt;
        }

          

  SqlParameter类的属性Direction作用在获取或者设置一个值,该值指示参数是只可以输入,只可以输出,双向,还是存储过程返回值参数。

  paras[5].Direction= ParameterDirection.Output;得到存储过程执行后的输出值

  paras[6].Direction= ParameterDirection.ReturnValue;得到存储过程执行后的返回值

  要实现这个获取值需要在存储过程中将参数设为OUTPUT类型:@RecordCount int OUTPUT,详看存储过程。

总结


  代码实现完成了,整个过程很清楚了,不过感觉还有很多不太明白的地方,可能就是对其中的细节上理解的不太明白,也是以前没有接触过不熟悉的原因吧。不纠结了,最后能够从全局上掌握这个方法,会用了即可吧。
  学习牛腩的时候用过第三方控件AspNetPager,只要引入封装的.dll就能实现真分页,原理上应该是一样的,而且它都给你封装好了,拿来用就行,怎么封装出来的,看来还要好好研究。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 32
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值