概述
分页就是把数据分成一页一页的,然后再显示出来,从这句话的理解中我们可以有多种方案:一次从数据库中只取出当前页面的数据,如需显示下一页数据,再从数据库中取出本次页面的数据;一次从数据库中取出所有的数据,然后,显示显示当前页面的数据,如需显示下一页数据,再一次从数据库中取出所有数据,显示下一页数据,一次类推;一次从数据库中取出所有的数据,然后,显示本次页面数据,如需显示下一页的数据,不需要再一次从数据库取出数据,根据之前的数据,显示下一页面的数据。具体每种方案的优缺点、适用于哪种情况,在这里就不说了,合理使用这几种方案,可以使我们的系统更加的完美。下面是一些关于这几种方案在实现过程中需要掌握的一些知识。
GridView控件
使用GridView控件实现数据分页的功能,核心代码如下://打开分页功能
GridView1.AllowPaging = true;
//确定每页最大记录数
GridView1.PageSize = 2;
//绑定数据源
GridView1.DataSource = dt;
GridView1.DataBind();
//GridView控件的PageIndexChanging事件里代码的功能:实现点击某页就转化到某页数据
//把要转化到的页数赋值给控件的PageIndex属性
GridView1.PageIndex = e.NewPageIndex;
//从新绑定数据
……
AspNetPager分页控件
我们可以把分页这个整体分为为两个过程:分页逻辑运算和页面显示。GridView控件具有整个分页的功能,但是其分页逻辑运算不怎么好,所以,有了AspNetPager控件(没有显示页面数据的功能),对于AspNetPager控件,其在分页过程中用到的代码如下://设置总记录数的大小
AspNetPager.RecordCount = 10;
//设置每页记录数的大小
AspNetPager.PageSize = 2;
//AspNetPager控件的PageChanging事件里的代码如下
AspNetPager.CurrentPageIndex = e.NewPageIndex;
//重新绑定数据
……
数据库
对于一次些取完所有数据的SQL代码在这里就不说了,需要说一下的是另一种情况:一次取记录中一部分记录的情况。根据要求,我们可以得出SQL语句中应该包含每一页的记录数和页面示数,并且,我们还有保证他的正确性。具体代码如下:
--通用的SQL代码
select top 每页显示的记录数 * from A
where id not in
(select top (当前的页数-1) * 每页显示的记录数 id from A order by id desc)
order by id desc
解释:这个是比较通用的方法,主要意思是:总数为100人,按照顺序排好,A选前20个人,B选前10个人,从A从取出10个跟B中人不同的人。
-- 另一种SQL语句如下:
with tempTB as (
SELECT ROW_NUMBER() OVER (ORDER BY id desc)AS Row,
...
)
SELECT * FROM tempTB where Row between @startIndex and @endIndex
解释:这个SQL代码我们需要知道两个点:CTE和row_number() over (partition by column order by column)。CTE
CTE是公共表表达式,其产生的最大好处就是提升了SQL代码的可读性,当然,一定程度上也是提高了系统的性能,它是一个存储结果集的内存表(数据太多的话也会用到虚拟内存),且结果集只对其后一句SQL语句有效,并且,这个后一句SQL语句可以多次出现该结果集,CTE主要是递归的运用,下面是关于CTE的一些代码:--创建
with CTE_Test1
as
(
select id,title,content from news
), --引用多个不同的结果集的CET,可以同时创建多个
CTE_Test2
as
(
select id,categoryId from news
)
--使用;CTE_Test只能被紧跟其后一条SQL语句一次或多次访问
select * from CTE_Test1 as a
inner join CTE_Test2 as b
on a.id = b.id
order by a.id desc
--创建(递归)
with CTE_Test(id,categoryId,title)
as
(
--基本语句
select id,categoryId,title from news
union all
--递归语句
select news.id,news.categoryId,news.title from news inner join CTE_Test on news.id = CTE_Test.id
)
--使用
select * from CTE_Test
option(maxrecursion 2) --指定最大递归次数为2
临时表是为了记录大量的中间集;视图是为了简化复杂的联表查询;表变量是为了快速记录少量的中间集;CET是为了SQL代码的可读性。以上是笔者认为它们的主要作用,具体就不解释了。
row_number() over (partition by column order by column)
这个是一个函数,具体的作用就是在查询的结果集中添加一个字段,并且顺序的写出序号;partition by column的作用是是该函数分块进行书写相应的序号,例:A块和B块的序号的书写都是从1开始的。
DataTable向DataTalbe之间数据传递
当采用一次访问数据,数次使用数据的方案时,我们的基本操作就是,把总数据放到一个DataTable中,每一页的数据放到另一个DataTable中,我们绑定的时候,绑定每一页的数据,下面是DataTable和DataTable之间数据的传递代码://传递表头信息
//方法一
for (int i = 0; i < dt1.Columns.Count; i++)
{
dt2.Columns.Add(dt1.Columns[i].ColumnName);
}
//方法二
//复制一个相同的对象
dt2 = dt1.Copy();
//清空里面的数据
dt2.Rows.Clear();
//方法三
//复制一个对象,但该对象里没有相应的数据
dt2 = dt1.Clone();
//传递具体数据信息
for (int i = 0; i < dt1.Rows.Count; i++)
{
//方法一:添加一行数据
DataRow drq = dt2.NewRow();
drq.ItemArray = dt1.Rows[i].ItemArray;
dt2.Rows.Add(drq);
//方法二:添加一行数据
//dt2.ImportRow(dt.Rows[0]);
}
通过逻辑运算,找到从哪一行开始赋值。实例1
下面是采用每次从数据库取出一页数据的方案的实例,采用GridView和AspNetPager结合,具体代码如下using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
namespace Web
{
public partial class Test1 : System.Web.UI.Page
{
DataTable dt = new DataTable ();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//总的记录数是多少
anp.RecordCount = 4;
//每页显示的记录数
anp.PageSize = 2;
//获得数据
GetSource();
//绑定数据
BandSource();
}
}
//获得源数据
private void GetSource()
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = "Data Source=ip地址;Initial Catalog=数据库;User ID=登陆名;Pwd=密码";
cn.Open();
string strSql = "select top (@每页记录数) * from news where id not in (select top (@当前页减一的记录和) id from news order
by id desc) order by id desc";
SqlCommand cmd = new SqlCommand(strSql,cn);
SqlParameter[] sqlParams = new SqlParameter[] { new SqlParameter("@每页记录数", anp.PageSize), new SqlParameter("@当前页减
一的记录和", (anp.CurrentPageIndex - 1) * anp.PageSize) };
cmd.Parameters.AddRange(sqlParams);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
}
//绑定源数据
private void BandSource()
{
//绑定数据
GridView1.DataSource = dt; //设定数据源
GridView1.DataBind(); //绑定数据源
}
//索引页发生改变
protected void AspNetPager1_PageChanging(object src, Wuqi.Webdiyer.PageChangingEventArgs e)
{
//获得当前索引页示数
anp.CurrentPageIndex = e.NewPageIndex;
//重新获得数据,绑定数据
GetSource();
BandSource();
}
}
}
实例2
该实例是多次访问数据库,每一次返回所有数据的那个方案,采用GridView控件,具体代码如下:using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using BLL;
using System.Data;
using System.Data.SqlClient;
namespace Web
{
public partial class Test1 : System.Web.UI.Page
{
DataTable dt = new DataTable ();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//开启分页的功能
GridView2.AllowPaging = true;
//每页的大小为1
GridView2.PageSize = 1;
//绑定数据,并显示第一页
GridView2.DataSource = new NewsManger().SelectNewsAll();
GridView2.DataBind();
}
}
//索引页发生改变
protected void GridView2_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
//设置显示的页码
GridView1.PageIndex = e.NewPageIndex;
//从新绑定数据
GridView2.DataSource = new NewsManger().SelectNewsAll();
GridView2.DataBind();
}
}
}
实例1和2的前台界面设计没有贴出相应的代码,还有,实例2运用的是经典3层架构,BLL层的代码也没有贴出来,所以,如果要是用上述代码的话,还是要多多注意点。