信息来源: linqingfeng Blog
懒"序;
Visual Studio 2005推广的时间不算短了,它为我们带来的很多新特性使得开发更加高效和有趣.相信众多VS开发者抢鲜体验过并为此激动不已了.不论是IDE的格局还是 FrameWork的改进,都十分令人赏心悦目.在微软公布的诸多新特性里面,最为让我关注的部分,就是数据绑定.有过经验的朋友一定知道,在 FrameWork1.0甚至更早时期的版本,数据绑定控件和数据源提供的可选功能相当薄弱,为实现一个较为复杂的数据显示或操作需要而coding,都 是一件颇为恐怖的事情.VS2003中的DataGrid曾凭借其良好的功能集成,与SqlDataSource配合,为我们减轻了一定的负担,一直成为 数据绑定的首选.虽然它提供了相应的事件接口,但仍需要大量的代码才得以完成.微软的产品一向是助长开发者们的惰性的.自VS2005推出以来, GridView作为DataGrid不二的继承人,逐渐显露它的强大,慢慢为像我们这样的懒人接受并打算长期使用.加上有FrameWork2.0新品 ObjectDatasource的无缝支持,它俩简直就是数据绑定界天造地设的一对,使用非常省心,就一个词:"Perfection"...
"懒"归正传:
最近开场废话是多了点(可能是参加会议太多闹的.. ^_^!!).马上请出GridView & ObjectDataSource.
下面我将逐步展现一个分页的案例.
案例环境: WindowsXP SP2, VS2005 Team Suite,SqlServer2005(没有比这更糟的了....)
要求: 了解数据绑定控件的结构,数据源的运行机制,以及简单的绑定控件设计实现(那些内容足够再写一篇教程了,这里不再多叙.)
参 考: MSDN中提到,ObjectDataSource是唯一支持界面分页的数据源(除非自己来继承造一个,汗!),但示例仍 然是用SqlDataSource做数据源介绍的GirdView绑定.难道MS这么小气???(ps:打死俺也不说).
那好,就从那句介绍开始,咱们自己动手整出一个来.
按照常规,先准备一张表和一些存储过程,如下:
Table:MyUsers
UserID(int,primarykey,identity)--自动增加字段,用户ID标识列
UserName(nvarchar(50),notnull)--用户名
Description(nvarchar(50),notnull)--备注

Procedure:

CREATEPROCEDURE[dbo].[AddUser]--增加一个用户
@UserNamenvarchar(50),
@Descriptionnvarchar(50)
AS
BEGIN
SETNOCOUNTON;

begintransactiont

insertintoMyUsers(UserName,Description)
values(@UserName,@Description)

if@@error<>0
begin
rollbacktransactiont
end
else
begin
committransaction
end
END

CREATEPROCEDURE[dbo].[DeleteUserByUserID]--删除一个用户
@UserIDint
AS
BEGIN
SETNOCOUNTON;

BeginTransactiont

deletefromMyUserswhereUserID=@UserID

if@@error<>0
begin
rollbacktransactiont
end
else
begin
committransaction
end
END

CREATEPROCEDURE[dbo].[UpdateUser]--修改用户姓名或备注
@UserIDint,
@UserNamenvarchar(50),
@Descriptionnvarchar(50)
AS
BEGIN
SETNOCOUNTON;

begintransactiont

updateMyUsers
setUserName=@UserName,
Description=@Description
whereUserID=@UserID

if@@error<>0
begin
rollbacktransactiont
end
else
begin
committransactiont
end
END

CREATEPROCEDURE[dbo].[GetUsers]--得到用户列表,注意这里的参数
@RowIndexint,
@RecordCountint
AS
BEGIN
SETNOCOUNTON;

WithVUsersas(
select*,row_number()over(orderbyUserIDdesc)asRowNum
fromMyUsers
)

select*fromVUsers
whereRowNum>@RowIndexandRowNum<=(@RowIndex+@RecordCount)
END

CREATEPROCEDURE[dbo].[GetUsersCount]
AS
BEGIN
SETNOCOUNTON;
selectcount(UserID)fromMyUsers
END
这里详细说明一下倒数两个存储过程,GetUsers的参数RowIndex,不是页码(传说中的PageIndex),而是行索引,且从 0开始.这点特别要注意,因为要让ObjectDataSource自动取得当前需要的数据(界面级分页意味着当前需要显示多少数据只向数据库取多少,并 不会像其他数据源全总取出消耗性能.),依据也就是行索引和增量.GetUsersCount这个存储过程是为ObjectDataSource分页提供 总数的,它与分页的存储过程要保持一致.特别指的是有分页条件的情况,本人经常忘记(^_^||).否则GridView显示会不正常.
在WebSite新建一个DAL,假定类名为DataManager,给出代码片段如下:
usingSystem;
usingSystem.Data;
usingSystem.Data.SqlClient;
usingSystem.Configuration;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
usingSystem.Collections;
usingSystem.Collections.Generic;


/**////
///DataAccessLayer
///
publicclassDataManager


{
privateSqlConnectioncon=null;//连接对象
privateSqlCommandcmd=null;//command执行对象
privateSqlDataAdapterda=null;//适配器对象


/**////
///DAL对象构造
///
publicDataManager()


{
//
//TODO:Addconstructorlogichere
//
}


/**////
///打开数据库连接
///
privatevoidOpenConnection()


{
try


{
stringconString=ConfigurationManager.ConnectionStrings["localDB"].ConnectionString;
con=newSqlConnection(conString);
if(ConnectionState.Closed==con.State)


{
con.Open();
}
}
catch(SqlExceptionex)


{
thrownewException("数据库无法访问",ex);
}
}


/**////
///关闭数据库连接
///
privatevoidCloseConnection()


{
if(ConnectionState.Open==con.State)


{
try


{
con.Close();
}
catch(SqlExceptionex)


{
thrownewException("数据库无法关闭",ex);
}
}
}


/**////
///取得用户列表
///
///行索引
///页显示量(增量)
///用户列表数据集
publicDataSetGetUsers(introwIndex,intrecordCount)


{
OpenConnection();
try


{
cmd=newSqlCommand();
cmd.Connection=con;
cmd.CommandType=CommandType.StoredProcedure;
cmd.CommandText="GetUsers";

SqlParameterspRowIndex=newSqlParameter("@RowIndex",SqlDbType.Int,4);
spRowIndex.Direction=ParameterDirection.Input;
SqlParameterspRecordCount=newSqlParameter("@RecordCount",SqlDbType.Int,4);
spRecordCount.Direction=ParameterDirection.Input;

cmd.Parameters.Add(spRowIndex);
cmd.Parameters.Add(spRecordCount);

spRowIndex.Value=rowIndex;
spRecordCount.Value=recordCount;

da=newSqlDataAdapter(cmd);
DataSetds=newDataSet();

da.Fill(ds,"MyUsers");

returnds;
}
catch(SqlExceptionex)


{
thrownewException("无法取得有效数据",ex);
}
finally


{
CloseConnection();
}
}


/**////
///取得用户总数
///
///用户总数
publicintGetUsersCount()


{
OpenConnection();
try


{
cmd=newSqlCommand();
cmd.Connection=con;
cmd.CommandType=CommandType.StoredProcedure;
cmd.CommandText="GetUsersCount";
intcount=Convert.ToInt32(cmd.ExecuteScalar().ToString());
returncount;
}
catch(SqlExceptionex)


{
thrownewException("无法取得有效数据",ex);
}
finally


{
CloseConnection();
}
}对DAL也有几项说明,DataManager.GetUsers(int rowIndex, int recordCount)方法的参数只能有两个,
参数名可以随意,但意义却要与调用的存储过程GetUsers要一致,rowIndex必须是行索引,recordCount必须是页显示量.
OK!接下来在页面上放上一个GridView和一个ObjectDataSource,设置代码片段如下:

<asp:GridViewID="gvMyUsers"runat="server"AllowPaging="True"CellPadding="4"DataSourceID="objMyUsers"ForeColor="#333333"GridLines="None"AutoGenerateDeleteButton="True"AutoGenerateEditButton="True"AutoGenerateColumns="False"DataKeyNames="UserID"PageSize="10">
<FooterStyleBackColor="#507CD1"Font-Bold="True"ForeColor="White"/>
<RowStyleBackColor="#EFF3FB"/>
<EditRowStyleBackColor="#2461BF"/>
<SelectedRowStyleBackColor="#D1DDF1"Font-Bold="True"ForeColor="#333333"/>
<PagerStyleBackColor="#2461BF"ForeColor="White"HorizontalAlign="Center"/>
<HeaderStyleBackColor="#507CD1"Font-Bold="True"ForeColor="White"/>
<AlternatingRowStyleBackColor="White"/>
asp:GridView>
<asp:ObjectDataSourceID="objMyUsers"runat="server"EnablePaging="True"MaximumRowsParameterName="recordCount"
SelectCountMethod="GetUsersCount"SelectMethod="GetUsers"StartRowIndexParameterName="rowIndex"TypeName="DataManager">
asp:ObjectDataSource>指定每页显示最大数据量(页显示量)的参数:
MaximumRowsParameterName="recordCount"
指定取得数据总数方法:
SelectCountMethod="GetUsersCount"
指定分页方法:
SelectMethod="GetUsers"
指定起始行参数:
StartRowIndexParameterName="rowIndex"
指定前面方法所属类名(全限定名):
TypeName="DataManager
这几个设置是必须的,一定要对应.
现在轻轻的点击一下运行吧(什么什么?还没写事件?...我说老铁,都啥年月了,懒人还有用那玩儿吗?).到这里,一个最快速的分页其实已经做完了.
前面的步骤都是必须的,但仍然可以有一些变化.比如,若你已经按以往的办法写好了一个类似于
CreateProcedureGetUsers
@PageIndexint,
@PageSizeint
as
begin




end 这样的存储过程了,没关系,你在DAL的DataManager.GetUsers(int rowIndex, int recordCount)这里,
把rowIndex,recordCount在调用存储过程前转换成PageIndex,PageSize就好了,也不过是
PageIndex = rowIndex/recordCount +1; PageSize =recordCount;这样的语句就能搞定啦.再或者改存储过程里面也行(虽然有点不值得),不多说了.自己耍一把就知道了.
你一定心里还有疑问,没错,DataManager.GetUsers(int rowIndex, int recordCount)这个方法,更多时候需要多一些参数,也就是说,我们分页取数据的过程,还需要一些筛选条件,但这个方法是要给 ObjectDataSource的selectMethod方法,不能增加别的参数,形成矛盾怎么办??欲知解决之道,且等下回分解.....(快跑 啊.....鸡蛋来啦!!)
Posted on 2006-04-17 18:43
笑看千秋_R 书接上回,我们提到,如果我们分页的数据,在查询的存储过程中需要更多参数,在使用ObjectDataSource作为数据源完成界面级分页,我们必须 做一些其他的事情.为了让示例更为易懂,我们将上一次的MyUsers表变化一下,增加一个用户状态列.并增加两个存储过程.
Table:MyUsers
@UserID(int,primarykey,identity),
@UserName(nvarchar(50),notnull),
@Description(nvarchar(50),notnull),
@Status(bit,notnull)

Procedure:
createprocedure[dbo].[GetUsersByStatus]--通过状态得到用户列表
@RowIndexint,
@RecordCountint,
@Statusbit
AS
BEGIN
SETNOCOUNTON;

WithVUsersas(
select*,row_number()over(orderbyUserIDdesc)asRowNum
fromMyUserswhereStatus=@Status
)

select*fromVUsers
whereRowNum>@RowIndexandRowNum<=(@RowIndex+@RecordCount)
END

CREATEPROCEDURE[dbo].[GetUsersCountByStatus]--取得通过状态得到用户列表的总数
@Statusbit
AS
BEGIN
SETNOCOUNTON;
selectcount(UserID)fromMyUserswhereStatus=@Status
END 在WebSite的DataManager中,再增加两个带参数的分页查询的方法.下面介绍两种带参的分页查询方法的写法(原因是和ObjectDataSource的运行机制有关):
(1)
MSDN中提到,ObjectDataSource有这样一个事件:ObjectDataSources_Created,它将在每次ObjectDataSource
初始化TypeName指定的类时触发.也就是说,如果分页的方法需要除RowIndex,RecordCount外的其他参数的话可以
借助此事件来增加参数.由此,可以按下面方式增加分页方法:
1.在DataManager类中,增加一个属性
privatebool_Status;
publicboolStatus


{

get
{return_Status;}

set
{_Status=values;}
}

2.增加一个方法

publicDataSetGetUsers(introwIndex,intrecordCount)


{

/**////
///取得用户列表
///
///行索引
///页显示量(增量)
///用户列表数据集
publicDataSetGetUsers(introwIndex,intrecordCount)


{
OpenConnection();
try<