混在web上,那有不同分页打交道的,分页偏偏又是一个硬伤,总是不能找到一个通用的解决方法,即使用上分页自定义/用户控件感觉还是少了点什么,性能.
web页面一次一般显示10行数据为好,但往往很多时候我们从数据库中查出来上万条数据,这个时候我们要在上万条数据中显示10条,那就必须分页.分页的第一问题就是分页数据.
1.分页数据:分页的数据分为两种,一种是在数据库中只取需要的10条数据,这也是性能提升的标致,一种是全盘拖出,放到程序缓存中再用程序来分页.
1.1 第一种取数据方式有select top [PageSize] * from [Table] where id not in(select top [CurrentPage-1] [PageSize] id from [Table] ----用于access,mssql当中
另一种是存储过程,这也是最快的取数据方式
Code
ALTER PROCEDURE GetAuthors
@PageIndex int,
@PageSize int
AS
BEGIN
-- Set the page bounds
DECLARE @PageLowerBound int
DECLARE @PageUpperBound int
DECLARE @TotalRecords int
SET @PageLowerBound = @PageSize * (@PageIndex-1)
SET @PageUpperBound = @PageSize*@PageIndex-1
-- Create a temp table TO store the select results
CREATE TABLE #PageIndexForAuthors
(
IndexId int IDENTITY (0, 1) NOT NULL,
au_id varchar(11),
au_lname varchar(40),
au_fname varchar(20),
phone char(12),
address varchar(40),
city varchar(20),
state char(2),
zip char(5),
contract bit
)
-- Insert into our temp table
INSERT INTO #PageIndexForAuthors
(au_id ,au_lname,au_fname,phone,address,city,state,zip,contract)
SELECT *
FROM authors
ORDER BY au_id
SELECT @TotalRecords = @@ROWCOUNT
SELECT * FROM #PageIndexForAuthors
WHERE IndexId between @PageLowerBound AND @PageUpperBound
ORDER BY au_id
RETURN @TotalRecords
END
GO 上面这段存储过程是仿微软的写法,微软在Membership里面采用也是这存储过程分页.
其他数据库取数据也有不同,sql2005有行号函数,oracle也有,mysql就更好取了limit 10,20
1.2第二种就是全部数据取出来再做缓存,数据用程序处理,.ado/jdbc有定位法,Adapter.Fill()用这个填充需要的数据,GridView自定义分页事件就是使用这个,看到很多自定义控件也使用这种方式
2.分页采取何种方式了,现在网页都讲究Seo,所以在前台分页的时候我摒弃PostBack方式,而采用URL方式.不采PostBack也就不需要用到ViewState["PageNo"]存取数据,每次分页的时候都重新加载,所以视图状态就没撒用.
好了,现在很清楚,为了效率,为了SEO,混口饭吃真不容易,数据采用存储过程从数据库中取所需的数据,并返回总共条数.分页采用URL方式,一是为了urlRewrite和seo,至于postback提倡在后台分页,毕竟方便
那现在就到了实现阶段,数据显示控件肯定是Repeater/DataList/GridView统杀.刚开始我是想把分页控件和数据显示在一起,但是若使用存储过程传递参数比较麻烦,不使的存储过程参数个数是不一样的,所以决定采用数据显示和分页控件分离的方法,分页控件只传递总记录数就可以了.
所以即想当爹又当妈,那是很累的,现在主要使用存储过程从数据库取出所需的数据,分页控件又采用URL,到止分页效率高了,SEO也实现了,但是三层架构中不好使,三层架构中要传参中加页码也可以使,代码如下
这是页面代码:
Code
public partial class PagerDemo : System.Web.UI.Page
{
private int TotalRecords;
protected void Page_Load(object sender, EventArgs e)
{
Repeater1.DataSource = GetTable();
Repeater1.DataBind();
Pager1.TotalRecords = TotalRecords ;
}
private DataTable GetTable()
{
string connStr = ConfigurationManager.ConnectionStrings["pubsConnectionString"].ConnectionString;
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlParameter[] prms = new SqlParameter[3];
prms[0] = new SqlParameter("@PageIndex", SqlDbType.Int);
prms[0].Value = Pager1.PageIndex;
prms[1] = new SqlParameter("@PageSize", SqlDbType.Int);
prms[1].Value = Pager1.PageSize;
prms[2] = new SqlParameter("@TotalRecords", SqlDbType.Int);
prms[2].Direction = ParameterDirection.ReturnValue;
SqlCommand cmd = conn.CreateCommand();
cmd.Parameters.AddRange(prms);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "GetAuthors";
SqlDataAdapter Adapter = new SqlDataAdapter();
Adapter.SelectCommand = cmd;
try
{
conn.Open();
Adapter.Fill(dt);
TotalRecords = int.Parse(cmd.Parameters["@TotalRecords"].Value.ToString());
return dt;
}
catch (Exception ex)
{
throw ex;
}
}
}
} 这是用户控件代码:
Code
public partial class Pager : System.Web.UI.UserControl
{
private int _totalRecords;
private int _pageSize = 10;
private int _maxPagesShown = 10;
private System.Collections.Generic.List<string> queryString;
protected void Page_Load(object sender, EventArgs e)
{
SetPages();
}
public int TotalRecords
{
get { return _totalRecords; }
set { _totalRecords = value; }
}
public int PageIndex
{
get
{
return Request.QueryString["PageNo"] == null ? 1 : int.Parse(Request.QueryString["PageNo"]);
}
}
public int PageSize
{
get { return _pageSize; }
set { _pageSize = value; }
}
public int MaxPagesShown
{
set { _maxPagesShown = value; }
}
public int PageCount
{
get { return TotalRecords / PageSize + 1; }
}
private void SetPages()
{
Panel1.Controls.Clear();
HyperLink link;
if (PageIndex - _maxPagesShown > 1)
{
link = new HyperLink(); link.Text = "<<"; link.NavigateUrl = MakeLink("1"); Panel1.Controls.Add(link);
}
if (PageIndex > 1)
{
link = new HyperLink(); link.Text = "<"; link.NavigateUrl = MakeLink(PageIndex - 1); Panel1.Controls.Add(link);
}
for (int i = PageIndex - _maxPagesShown; i <= PageIndex + _maxPagesShown; i++)
{
if (i > 0 && i <= PageCount)
{
if (PageIndex == i)
{
link = new HyperLink(); link.Text = "Page " + i.ToString(); link.CssClass = "selected"; Panel1.Controls.Add(link);
}
else
{
link = new HyperLink(); link.Text = i.ToString(); link.NavigateUrl = MakeLink(i); Panel1.Controls.Add(link);
}
}
}
if (PageIndex < PageCount)
{
link = new HyperLink(); link.Text = ">"; link.NavigateUrl = MakeLink(PageIndex + 1); Panel1.Controls.Add(link);
}
if (PageIndex + _maxPagesShown < PageCount)
{
link = new HyperLink(); link.Text = ">>"; link.NavigateUrl = MakeLink(PageCount); Panel1.Controls.Add(link);
}
}
private string MakeLink(Object pageID)
{
string currentPageID = pageID.ToString();
queryString = new System.Collections.Generic.List<string>();
foreach (string key in Request.QueryString.Keys)
{
if (key != "PageNo")
{
queryString.Add(key + "=" + Request.QueryString[key]);
}
}
queryString.Add("PageNo=" + pageID.ToString());
string filePath = Request.CurrentExecutionFilePath;
return String.Format(filePath + "?{0}", String.Join("&", queryString.ToArray()));
}
} 我将代码打包,欢迎下载,给出意见...
/Files/izxp/Pager.rar