2023年6月21日发(作者:)

⼤数据量下的C#分页 对于⾮常⼤的数据模型⽽⾔,分页检索时,每次都加载整个数据源⾮常浪费。通常的选择是检索页⾯⼤⼩的块区的数据,⽽⾮检索所有的数据,然后单步执⾏当前⾏。

本⽂演⽰的DataGrid和Sql Server 实现⼤数据量下的分页,为了便于实现演⽰,数据表采⽤了Northwind数据库的Orders表(830条记录)。 如果数据表中有唯⼀的⾃增索引,并且这个字段没有出现断号现象。检索页⾯⼤⼩的块区数据就⾮常简单了。通过简单的Sql语句就可以实现这个功能:select * from orders where orderid between 10248 and 10253其中,开始编号为:(CurrentPageIndex - 1) * PageSize 结束编号为:CurrentPageIndex * PageSize当然,如果这个字段断号不是很严重,⽽且允许不是很严格的按照每页条数分页,这样的⽅法也是可以⽤的。 如果这个字段断号,或者需要按照其他条件排序分页,就要复杂些了。⾸先要获得这个页⾯需要显⽰的编号,然后再按照这个编号获得需要的块区数据。根据编号获得块区数据很简单。不过⽤下⾯⽅式获得数据排序并不是按照指定的id列表顺序,这时候还要附加order by命令。select * from orders where orderid in (10248,10249,10250,10251,10252,10253) order by orderid desc获得这个页⾯需要显⽰的编号列表就复杂多了,⽽且有多种⽅案:⽅案⼀:维护⼀个表,这个表记录需要显⽰的这些编号排序顺序。(这个表可以是临时表,也可以是物理表)。下⾯演⽰了利⽤⼀个全局临时表。这个全局临时表记录需要显⽰的编号。注意排序,这⾥的order by 就是需要显⽰的排序顺序。create table ##temptable(iid int IDENTITY (1, 1) NOT NULL,mainid int NOT NULL)insert ##temptable(mainid) select OrderID from orders order by OrderID descselect * from ##temptabledrop table ##temptable -- 实际执⾏时候,删除全部临时表当然不再这⾥执⾏。这个临时表存在,获得指定分页的分块数据就很简单了。看下⾯代码:create table ##temptable(iid int IDENTITY (1, 1) NOT NULL,mainid int NOT NULL)insert ##temptable(mainid) select OrderID from orders order by OrderID descdeclare @PageSize int,@CurrPage int,@strSQL varchar(2000),@IDStr varchar(1000)select @PageSize = 30select @CurrPage = 2select @IDStr = ''select @IDStr = @IDStr + ltrim(rtrim(str(MainID))) + ',' from ##temptable

where iid between ((@CurrPage-1)*@PageSize+1) and @CurrPage*@PageSizeif @IDStr <> ''

beginselect @IDStr = left(@IDStr,len(@IDStr)-1)endselect @strSQL = 'select * from orders where OrderID in () order by OrderID desc 'exec(@strSQL)drop table ##temptable注意:实际使⽤这个⽅案的时候,还要考虑何时更新这个全局临时表,⼀般是放到计划任务中,定时更新这个汇总表。⽅案⼆:每次都去查询,每次获得最新的编号顺序。由于这时候不存在这个临时表,书写获得需要显⽰页⾯的编号的字符串就需要点技巧,看下⾯的代码:declare @PageSize int,@CurrPage int,@topnum int,@previous intselect @PageSize = 30select @CurrPage = 2select @topnum = @CurrPage * @PageSizeselect @previous = (@CurrPage - 1) * @PageSizedeclare @i int,@IDStr nvarchar(500),@strSQL nvarchar(1000)select @i = 0select @strSQL = N''select @strSQL = @strSQL + N' select top '+str(@topnum)+ ' @i = @i + 1 'select @strSQL = @strSQL + N', @IdStr = 'select @strSQL = @strSQL + N'case when @i > '+str(@previous)+' then @IdStr + ltrim(rtrim(str(OrderID))) + '','' 'select @strSQL = @strSQL + N'else N''''end 'select @strSQL = @strSQL + N'from Orders 'select @strSQL = ltrim(rtrim(@strSQL)) + N' order by OrderID desc 'Select @IdStr = N''exec sp_executesql @strSQL,N'@i int,@IdStr varchar(500) output',@i,@IdStr outputif len(rtrim(ltrim(@IdStr))) > 0beginselect @IdStr = left(@IdStr,len(@IdStr)-1)endselect @strSQL = 'select * from orders where OrderID in (exec(@strSQL) 的 DataGrid 提供了使⽤这种分区的数据的⽅法。 DataGrid 通过 AllowCustomPaging 和 VirtualItemCount 属性⽀持块区操作。如果 AllowCustomPaging 为 true,则 DataGrid 不会根据 CurrentPageIndex 计算数据模型中的起始显⽰位置。DataGrid 将显⽰数据模型中的所有数据,⽽页导航栏将当前位置报告为 (VirtualItemCount+PageSize-1)/PageSize 之 CurrentPageIndex 页。下⾯的⽰例说明此功能。protected void BindDataGrid(int currpage){string strConn = "Data Source=(local);Integrated Security=SSPI;database=Northwind";// 请确认 机器名/ASPNET ⽤户可以访问Northwind数据库SqlCommand cmd = new SqlCommand();SqlConnection conn = new SqlConnection(strConn);SqlParameter[] parms = new SqlParameter[] {new SqlParameter("@PageSize",),new SqlParameter("@CurrPage",),new SqlParameter("@SearchSql",ar,128),new SqlParameter("@Count",),};parms[0].Value = ze;parms[1].Value = (currpage+1);

// 数据库的分页算法第⼀页是1 DataGrid的第⼀页是0parms[2].Value = ;parms[3].Direction = ;parms[3].Value = ;DataSet DS = new DataSet();try

{if ( != ) ();tion = conn;dText = "Selected_Page_List";dType = Procedure;if (parms != null)

{foreach (SqlParameter parm in parms)(parm);}SqlDataAdapter DA = new SqlDataAdapter(cmd);(DS);int aa = 32(parms[3].ng());();if (currpage == 0){lItemCount = aa;}tPageIndex = currpage;urce = DS;nd();}catch(Exception ewx){(); (ng());();}}void Page_Load(Object sender, EventArgs E ) {if (!IsPostBack)

{BindDataGrid(0);// 第⼀次打开这个页⾯,访问分页的第⼀页}}void MyDataGrid_Page(Object sender, DataGridPageChangedEventArgs e) {BindDataGrid(eIndex);}如果你有更多数据量的表稍加修改,也可以使⽤本演⽰程序。其下是演⽰代码下载,演⽰代码使⽤的是⽅案⼆。使⽤⽅法看⽂件。整个演⽰代码 下载这⾥演⽰了利⽤DataGrid 的这个功能(没有本⽂中讨论的利⽤存储过程获得分区数据)。如对DataGrid的这个功能不太熟悉,请先看这⾥。

2023年6月21日发(作者:)

⼤数据量下的C#分页 对于⾮常⼤的数据模型⽽⾔,分页检索时,每次都加载整个数据源⾮常浪费。通常的选择是检索页⾯⼤⼩的块区的数据,⽽⾮检索所有的数据,然后单步执⾏当前⾏。

本⽂演⽰的DataGrid和Sql Server 实现⼤数据量下的分页,为了便于实现演⽰,数据表采⽤了Northwind数据库的Orders表(830条记录)。 如果数据表中有唯⼀的⾃增索引,并且这个字段没有出现断号现象。检索页⾯⼤⼩的块区数据就⾮常简单了。通过简单的Sql语句就可以实现这个功能:select * from orders where orderid between 10248 and 10253其中,开始编号为:(CurrentPageIndex - 1) * PageSize 结束编号为:CurrentPageIndex * PageSize当然,如果这个字段断号不是很严重,⽽且允许不是很严格的按照每页条数分页,这样的⽅法也是可以⽤的。 如果这个字段断号,或者需要按照其他条件排序分页,就要复杂些了。⾸先要获得这个页⾯需要显⽰的编号,然后再按照这个编号获得需要的块区数据。根据编号获得块区数据很简单。不过⽤下⾯⽅式获得数据排序并不是按照指定的id列表顺序,这时候还要附加order by命令。select * from orders where orderid in (10248,10249,10250,10251,10252,10253) order by orderid desc获得这个页⾯需要显⽰的编号列表就复杂多了,⽽且有多种⽅案:⽅案⼀:维护⼀个表,这个表记录需要显⽰的这些编号排序顺序。(这个表可以是临时表,也可以是物理表)。下⾯演⽰了利⽤⼀个全局临时表。这个全局临时表记录需要显⽰的编号。注意排序,这⾥的order by 就是需要显⽰的排序顺序。create table ##temptable(iid int IDENTITY (1, 1) NOT NULL,mainid int NOT NULL)insert ##temptable(mainid) select OrderID from orders order by OrderID descselect * from ##temptabledrop table ##temptable -- 实际执⾏时候,删除全部临时表当然不再这⾥执⾏。这个临时表存在,获得指定分页的分块数据就很简单了。看下⾯代码:create table ##temptable(iid int IDENTITY (1, 1) NOT NULL,mainid int NOT NULL)insert ##temptable(mainid) select OrderID from orders order by OrderID descdeclare @PageSize int,@CurrPage int,@strSQL varchar(2000),@IDStr varchar(1000)select @PageSize = 30select @CurrPage = 2select @IDStr = ''select @IDStr = @IDStr + ltrim(rtrim(str(MainID))) + ',' from ##temptable

where iid between ((@CurrPage-1)*@PageSize+1) and @CurrPage*@PageSizeif @IDStr <> ''

beginselect @IDStr = left(@IDStr,len(@IDStr)-1)endselect @strSQL = 'select * from orders where OrderID in () order by OrderID desc 'exec(@strSQL)drop table ##temptable注意:实际使⽤这个⽅案的时候,还要考虑何时更新这个全局临时表,⼀般是放到计划任务中,定时更新这个汇总表。⽅案⼆:每次都去查询,每次获得最新的编号顺序。由于这时候不存在这个临时表,书写获得需要显⽰页⾯的编号的字符串就需要点技巧,看下⾯的代码:declare @PageSize int,@CurrPage int,@topnum int,@previous intselect @PageSize = 30select @CurrPage = 2select @topnum = @CurrPage * @PageSizeselect @previous = (@CurrPage - 1) * @PageSizedeclare @i int,@IDStr nvarchar(500),@strSQL nvarchar(1000)select @i = 0select @strSQL = N''select @strSQL = @strSQL + N' select top '+str(@topnum)+ ' @i = @i + 1 'select @strSQL = @strSQL + N', @IdStr = 'select @strSQL = @strSQL + N'case when @i > '+str(@previous)+' then @IdStr + ltrim(rtrim(str(OrderID))) + '','' 'select @strSQL = @strSQL + N'else N''''end 'select @strSQL = @strSQL + N'from Orders 'select @strSQL = ltrim(rtrim(@strSQL)) + N' order by OrderID desc 'Select @IdStr = N''exec sp_executesql @strSQL,N'@i int,@IdStr varchar(500) output',@i,@IdStr outputif len(rtrim(ltrim(@IdStr))) > 0beginselect @IdStr = left(@IdStr,len(@IdStr)-1)endselect @strSQL = 'select * from orders where OrderID in (exec(@strSQL) 的 DataGrid 提供了使⽤这种分区的数据的⽅法。 DataGrid 通过 AllowCustomPaging 和 VirtualItemCount 属性⽀持块区操作。如果 AllowCustomPaging 为 true,则 DataGrid 不会根据 CurrentPageIndex 计算数据模型中的起始显⽰位置。DataGrid 将显⽰数据模型中的所有数据,⽽页导航栏将当前位置报告为 (VirtualItemCount+PageSize-1)/PageSize 之 CurrentPageIndex 页。下⾯的⽰例说明此功能。protected void BindDataGrid(int currpage){string strConn = "Data Source=(local);Integrated Security=SSPI;database=Northwind";// 请确认 机器名/ASPNET ⽤户可以访问Northwind数据库SqlCommand cmd = new SqlCommand();SqlConnection conn = new SqlConnection(strConn);SqlParameter[] parms = new SqlParameter[] {new SqlParameter("@PageSize",),new SqlParameter("@CurrPage",),new SqlParameter("@SearchSql",ar,128),new SqlParameter("@Count",),};parms[0].Value = ze;parms[1].Value = (currpage+1);

// 数据库的分页算法第⼀页是1 DataGrid的第⼀页是0parms[2].Value = ;parms[3].Direction = ;parms[3].Value = ;DataSet DS = new DataSet();try

{if ( != ) ();tion = conn;dText = "Selected_Page_List";dType = Procedure;if (parms != null)

{foreach (SqlParameter parm in parms)(parm);}SqlDataAdapter DA = new SqlDataAdapter(cmd);(DS);int aa = 32(parms[3].ng());();if (currpage == 0){lItemCount = aa;}tPageIndex = currpage;urce = DS;nd();}catch(Exception ewx){(); (ng());();}}void Page_Load(Object sender, EventArgs E ) {if (!IsPostBack)

{BindDataGrid(0);// 第⼀次打开这个页⾯,访问分页的第⼀页}}void MyDataGrid_Page(Object sender, DataGridPageChangedEventArgs e) {BindDataGrid(eIndex);}如果你有更多数据量的表稍加修改,也可以使⽤本演⽰程序。其下是演⽰代码下载,演⽰代码使⽤的是⽅案⼆。使⽤⽅法看⽂件。整个演⽰代码 下载这⾥演⽰了利⽤DataGrid 的这个功能(没有本⽂中讨论的利⽤存储过程获得分区数据)。如对DataGrid的这个功能不太熟悉,请先看这⾥。