永远的学生

qindgfly

导航

用于存储过程分页的控件

    对于少量的数据,我们可以用GridView的自带分页功能,而如果数据量大了,这种方式就显得有些笨拙了,在网上查了查,发现很多高手都用分页的存储过程来对数据进行按需查询。有前辈把存储过程写成了通用的,我弄了几个这种通用存储过程试了试,就是用不对啊。最后就想自己写个吧,些是写出来了,可毕竟自己功力不够啊,写出的存储过程有很多局限性,例如:只能针对单表,表的主键类型不同的话还要修改一下存储过程才可用。不过我自己用,有时候还是可以减轻一些工作了。
    现在面临的问题是,在UI层如何来调用呢,我们要根据用户的操作来确定应该查询哪些记录,于是根据我的需求,写了个自定义控件来实现这个功能(也许我的工作是画蛇添足了,或许有其他更好的分页方?)。首先写了一个符合控件(就是显示“上页、下页”的哪些东西了),来改变和记录用户选择的页数,另外写了一个继承自ObjectDataSource的控件。两个控件协同工作,完成分页功能。
   下面贴出代码:

一、SQLServer部分
  分页存储过程如下:
/*-----------
单表通用分页存储过程
------------
*/



IF EXISTS((SELECT NAME FROM SYSOBJECTS WHERE NAME='SingleTableCommonPager'AND TYPE='P'))
    
DROP PROCEDURE SingleTableCommonPager
GO

set QUOTED_IDENTIFIER ON 
GO
SET ANSI_NULLS OFF 
GO

CREATE PROCEDURE SingleTableCommonPager
@TableName VARCHAR(255),        --表名
@PrimaryKey VARCHAR(255),        --表的主键
@Condition VARCHAR(2000)=NULL,        --查询条件
@OrderBy VARCHAR(500)=NULL,        --排序方式
@GroupBy VARCHAR(255)=NULL,        --分组
@PageIndex INT=0,            --当前页
@PageSize INT=5,            --页大小
@PageCount INT OUTPUT,            --页数
@TotalRecords INT OUTPUT        --总记录数
AS
BEGIN

set   nocount   on
-- Set the page bounds
DECLARE @PageLowerBound int
DECLARE @PageUpperBound int
SET @PageLowerBound = @PageSize * @PageIndex
SET @PageUpperBound = @PageSize - 1 + @PageLowerBound

-- Create a temp table TO store the select results
--
DECLARE @CreateTempTable VARCHAR(500)
--
SET @CreateTempTable='CREATE TABLE #PageIndex(IndexId int IDENTITY (0, 1) NOT NULL,'++')'

CREATE TABLE #PageIndex
(
    IndexId 
int IDENTITY (01NOT NULL,
    UniqueId 
uniqueidentifier
)



--
DECLARE @Select VARCHAR(5000)
SET @Select='INSERT INTO #PageIndex(UniqueId)SELECT '+@PrimaryKey
IF(@Condition IS NOT NULL)SET @Select=@Select+' WHERE '+@Condition
SET @Select=@Select+' FROM '+@TableName
IF(@OrderBy IS NOT NULL)SET @Select=@Select+' ORDER BY '+@OrderBy
IF(@GroupBy IS NOT NULL)SET @Select=@Select+' GROUP BY '+@GroupBy

-- Insert into our temp table
EXEC(@Select)

--Set total record count and page size
SET @TotalRecords=@@ROWCOUNT
SET @PageCount=@TotalRecords/@PageSize
IF(@TotalRecords%@PageSize<>0)
    
SET @PageCount=@PageCount+1



--select result
DECLARE @Sel VARCHAR(500)
SET @Sel='SELECT t.*'+' FROM #PageIndex p,'+@TableName+' t WHERE p.UniqueId=t.'+@PrimaryKey+
    
' AND p.IndexId >= '+cast(@PageLowerBound as varchar+' AND p.IndexId <=' + cast(@PageUpperBound as varchar)
set   nocount   off
EXEC(@Sel)
END
GO
SET QUOTED_IDENTIFIER OFF 
GO
SET ANSI_NULLS ON 
GO

我的表是这样的:
--CREATE DATABASE ZrkjDb
GO
USE ZrkjDb
GO

--===============================
/*
  创建成功案例表
*/

--===============================
IF(NOT EXISTS(SELECT NAME,TYPE FROM SYSOBJECTS WHERE NAME='ZRCase' AND TYPE='U'))
BEGIN
CREATE TABLE ZRCase
(
CaseId 
UNIQUEIDENTIFIER DEFAULT(NEWID()) PRIMARY KEY,
CaseTitle 
NVARCHAR(100NOT NULL,        --案例名称
CaseSite NVARCHAR(100),                --案例网址
CaseBreviaryImage NVARCHAR(200),        --案例缩略图
CaseOriginalImage NVARCHAR(200),        --案例原图
CaseDescription TEXT,                --案例描述
ShowInMainPage BIT DEFAULT(0),            --是否显示在首页
CaseOrder INT DEFAULT(0),            --排序的顺序,针对首页显示的案例,数字越大,显示越前
AddDate SMALLDATETIME DEFAULT(GETDATE())    --添加时间
)
END


获取记录的存储过程:
--===============================
/*
存储过程 P_ZRCase_Get 根据指定的参数
获取相关的记录 
*/

--===============================
IF(EXISTS(SELECT NAME FROM SYSOBJECTS WHERE NAME='P_ZRCase_Get' AND TYPE='P'))
   
DROP PROCEDURE P_ZRCase_Get
GO
CREATE PROCEDURE P_ZRCase_Get
@Index INT=0,            --当前页
@Size INT=10,            --页大小
@Count INT OUTPUT,        --页数
@Total INT OUTPUT        --总记录数
AS
BEGIN

EXEC SingleTableCommonPager
@TableName='ZRCase',        --表名
@PrimaryKey='CaseId',        --表的主键
@Condition=NULL,        --查询条件
@OrderBy='AddDate desc',    --排序方式
@GroupBy=NULL,            --分组
@PageIndex=@Index,        --当前页
@PageSize=@Size,        --页大小
@PageCount=@Count out,        --页数
@TotalRecords=@Total out    --总记录数


END 
GO



二、自定义控件代码:

分页控件(Pager.cs):
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Zrkj.WebControl
{
    [DefaultProperty(
"Text")]
    [ToolboxData(
"<{0}:Pager runat=server></{0}:Pager>")]
    
public class Pager : CompositeControl
    
{
        
属性

        
/// <summary>
        
/// 初始化一些参数
        
/// </summary>
        
/// <param name="e"></param>

        protected override void OnInit(EventArgs e)
        
{
            
this.Index = 0;
            
this.Size = 10;
            
this.ShowNextPreButton = true;
            
this.ShowFigureButton = true;
            
this.ShowDropDownList = true;
            
base.OnInit(e);
        }



        
protected override void CreateChildControls()
        
{
            Controls.Clear();

            
创建“首页,上一页,下一页,尾页的按钮”


            
创建数字分页的按钮


            
创建分页下拉列表


            
创建显示总页数,总记录数,当前页数等信息的标签
        }



        
/// <summary>
        
/// 控件的呈现
        
/// </summary>
        
/// <param name="writer"></param>

        protected override void Render(HtmlTextWriter writer)
        
{
            _FirstPageButton.RenderControl(writer);
            
            
if (_ShowNextPreButton)
            
{
                _PreviousPageButton.RenderControl(writer);
            }


            
if (_ShowFigureButton)
            
{
                
foreach (object obj in btn)
                
{
                    LinkButton link 
= (LinkButton)obj;
                    link.RenderControl(writer);
                }

            }


            
if(_ShowNextPreButton)
            
{
                _NextPageButton.RenderControl(writer);
            }


            _LastPageButton.RenderControl(writer);

            
if (_ShowDropDownList)
            
{
                ddl.RenderControl(writer);
            }


            writer.Write(
"");
            _CountLable.RenderControl(writer);
            writer.Write(
" 页");
            _TotalLable.RenderControl(writer);
            writer.Write(
"条记录");          
            writer.Write(
" 当前第");
            _CurrentPageIndexLable.RenderControl(writer);
            writer.Write(
"");
            writer.Write(
"每页显示");
            _SizeLable.RenderControl(writer);
            writer.Write(
"");
        }



        
protected override void OnPreRender(EventArgs e)
        
{
            
//如果当前页数小于等于0,并且只有一页的时候,所有按钮不可用
            if (Index <= 0 && Count <= 1)
            
{
                _FirstPageButton.Enabled 
= false;
                _PreviousPageButton.Enabled 
= false;
                _NextPageButton.Enabled 
= false;
                _LastPageButton.Enabled 
= false;
            }

            
//如果当前页数小于等于0,但页数大于1的时候,上页/首页的按钮不可用,下页/尾页的按钮可用
            else if (Index <= 0 && Count > 1)
            
{
                _FirstPageButton.Enabled 
= false;
                _PreviousPageButton.Enabled 
= false;
                _NextPageButton.Enabled 
= true;
                _LastPageButton.Enabled 
= true;
            }

            
//如果当前页数大于0,而又小于总页数减1的时候所有按钮可用
            else if (Index > 0 && Index < Count-1)
            
{
                _FirstPageButton.Enabled 
= true;
                _PreviousPageButton.Enabled 
= true;
                _NextPageButton.Enabled 
= true;
                _LastPageButton.Enabled 
= true;
            }

            
//当当前页数大于等于总页数加一的时候,上页/首页的按钮可用,下页/尾页的按钮不可用
            else if (Index >= Count - 1)
            
{
                _FirstPageButton.Enabled 
= true;
                _PreviousPageButton.Enabled 
= true;
                _NextPageButton.Enabled 
= false;
                _LastPageButton.Enabled 
= false;
            }



            
//当前页的按钮不可用
            for(int i=0;i<btn.Count;i++)
            
{
                LinkButton link 
= btn[i];
                
if (i == Index)
                
{
                    link.Enabled 
= false;
                }

                
else
                
{
                    link.Enabled 
= true;
                }

            }


            _TotalLable.Text 
= Total.ToString();
            _CountLable.Text 
= Count.ToString();
            _CurrentPageIndexLable.Text 
= Convert.ToString(Index + 1);
            _SizeLable.Text 
= Size.ToString();

            
base.OnPreRender(e);
        }



        
protected void OnButtonCommand(object obj, CommandEventArgs e)
        
{
            
switch (e.CommandName)
            
{
                
case "First":
                    Index 
= 0;
                    
break;
                
case "Previous":
                    Index
--;
                    
break;
                
case "Next":
                    Index
++;
                    
break;
                
case "Last":
                    Index 
= Count-1;
                    
break;
                
case "Figure":
                    Index 
= Convert.ToInt32(e.CommandArgument);
                    
break;
            }

            OnCommand(e);
        }


        
protected void ddl_SelectedIndexChanged(object obj, EventArgs e)
        
{
            DropDownList dropdown 
= (DropDownList)obj;
            Index 
= Convert.ToInt32(dropdown.SelectedValue);
            OnCommand(e);
        }




        
protected virtual void OnCommand(EventArgs e)
        
{
            EventHandler SubmitHandler 
=
                (EventHandler)Events[EventSubmitKey];
            
if (SubmitHandler != null)
            
{
                SubmitHandler(
this, e);
            }

        }

    }

}


数据源控件(PagedObjectDataSource)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Zrkj.WebControl
{
    [DefaultProperty(
"Text")]
    [ToolboxData(
"<{0}:PagedObjectDataSource runat=server></{0}:PagedObjectDataSource>")]
    
public class PagedObjectDataSource : ObjectDataSource
    
{
        
private string _PagerControl;
        [Browsable(
true)]
        [Category(
"分页扩展")]
        [Description(
"用于分页的控件")]
        
public string PagerControl
        
{
            
get return _PagerControl; }
            
set { _PagerControl = value; }
        }



        
private string _TotalParamName;
        [Browsable(
true)]
        [Category(
"分页扩展")]
        [Description(
"总记录数的参数名")]
        [DefaultValue(
"Total")]
        
public string TotalParamName
        
{
            
get return _TotalParamName; }
            
set { _TotalParamName = value; }
        }



        
private string _CountParamName;
        [Browsable(
true)]
        [Category(
"分页扩展")]
        [Description(
"总页数的参数名")]
        [DefaultValue(
"Count")]
        
public string CountParamName
        
{
            
get return _CountParamName; }
            
set { _CountParamName = value; }
        }



        
private string _SizeParamName;
        [Browsable(
true)]
        [Category(
"分页扩展")]
        [Description(
"页大小的参数名")]
        [DefaultValue(
"Size")]
        
public string SizeParamName
        
{
            
get return _SizeParamName; }
            
set { _SizeParamName = value; }
        }



        
private string _IndexParamName;
        [Browsable(
true)]
        [Category(
"分页扩展")]
        [Description(
"当前页数的参数名")]
        [DefaultValue(
"Index")]
        
public string IndexParamName
        
{
            
get return _IndexParamName; }
            
set { _IndexParamName = value; }
        }






        
public PagedObjectDataSource()
        
{
            
this._CountParamName = "Count";
            
this._IndexParamName = "Index";
            
this._SizeParamName = "Size";
            
this._TotalParamName = "Total";
            
            
this.Selected+=new ObjectDataSourceStatusEventHandler(PagedObjectDataSource_Selected);
            
this.Selecting+=new ObjectDataSourceSelectingEventHandler(PagedObjectDataSource_Selecting);
        }



        
void PagedObjectDataSource_Selecting(object obj, ObjectDataSourceSelectingEventArgs e)
        
{
            
if (string.IsNullOrEmpty(_PagerControl))
            
{
                
throw new Exception("必须为控件" + ID + "指定用于分页的控件的ID");
            }


            Pager pager 
= (Pager)Page.FindControl(_PagerControl);
            
if (pager == null)
            
{
                
throw new Exception("没有找到控件" + _PagerControl);
            }


            
if (SelectParameters[_IndexParamName] == null)
            
{
                
throw new Exception("指定的参数名" + _IndexParamName + "不正确,不包含该参数");
            }


            
if (SelectParameters[_SizeParamName] == null)
            
{
                
throw new Exception("指定的参数名" + _SizeParamName + "不正确,不包含该参数");
            }


            e.InputParameters[_IndexParamName] 
= pager.Index.ToString();
            e.InputParameters[_SizeParamName] 
= pager.Size.ToString();
        }



        
void PagedObjectDataSource_Selected(object obj, ObjectDataSourceStatusEventArgs e)
        
{
            
if (string.IsNullOrEmpty(_PagerControl))
            
{
                
throw new Exception("必须为控件" + ID + "指定用于分页的控件的ID");
            }


            Pager pager 
= (Pager)Page.FindControl(_PagerControl);
            
if (pager == null)
            
{
                
throw new Exception("没有找到控件" + _PagerControl);
            }


            
if (e.OutputParameters[_TotalParamName] == null)
            
{
                
throw new Exception("不能获取名为" + _TotalParamName + "的参数");
            }


            
if (e.OutputParameters[_CountParamName] == null)
            
{
                
throw new Exception("不能获取名为" + _TotalParamName + "的参数");
            }

                        
            pager.Total 
= Convert.ToInt32(e.OutputParameters[_TotalParamName]);
            pager.Count 
= Convert.ToInt32(e.OutputParameters[_CountParamName]);
        }

    }

}


三、前台调用代码:

Default.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="tst_Default" %>
<%@ Register Assembly="Zrkj.WebControl" Namespace="Zrkj.WebControl" TagPrefix="cc1" %>

<!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>无标题页</title>
</head>
<body>
    
<form id="form1" runat="server">
        
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="PagedObjectDataSource1">
            
<Columns>
                
<asp:BoundField DataField="CaseTitle" HeaderText="CaseTitle" SortExpression="CaseTitle" />
                
<asp:BoundField DataField="CaseOrder" HeaderText="CaseOrder" SortExpression="CaseOrder" />
                
<asp:CheckBoxField DataField="ShowInMainPage" HeaderText="ShowInMainPage" SortExpression="ShowInMainPage" />
                
<asp:BoundField DataField="CaseSite" HeaderText="CaseSite" SortExpression="CaseSite" />
            
</Columns>
        
</asp:GridView>
        
<cc1:Pager ID="Pager1" runat="server" OnCommand="Pager1_Command" Size="8" />
        
<cc1:PagedObjectDataSource ID="PagedObjectDataSource1" runat="server" PagerControl="Pager1" SelectMethod="GetCases" TypeName="Zrkj.WebDataProxy.CaseDataProxy">
            
<SelectParameters>
                
<asp:Parameter Name="Index" Type="Int32" />
                
<asp:Parameter Name="Size" Type="Int32" />
                
<asp:Parameter Direction="Output" Name="Count" Type="Int32" />
                
<asp:Parameter Direction="Output" Name="Total" Type="Int32" />
            
</SelectParameters>
        
</cc1:PagedObjectDataSource>
    
</form>
</body>
</html>

Default.aspx.cs:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Zrkj.WebDataProxy;
using Zrkj.Model;
public partial class tst_Default : System.Web.UI.Page
{
    
protected void Page_Load(object sender, EventArgs e)
    
{
       
    }

    
protected void Pager1_Command(object sender, EventArgs e)
    
{
        GridView1.DataBind();
    }

}


至此,分页功能基本实现。

如果哪位仁兄在网上无意之中看到这篇文章,请勿见笑。
初学者,战战兢兢!

posted on 2007-08-06 10:24  东国先生  阅读(739)  评论(1编辑  收藏  举报