|
|
用.net制作排序、分页解决数据大的问题
以下内容含脚本,或可能导致页面不正常的代码
一、概述:
Datagrid在web应用程式中经常用到,但是Datagrid控件本身提拱的排序,分页功能对于有着大量记录的表来说,按它的做法是不现实的,如一个表有20万记录,按Datagrid本身的排序和分页的原理,必须把所有的记录全部取回,再进行分页,这对服务器的内存及响应的速度是一个挑战。本论文提供了这样一个解决方案,就是只从数据库中取回你所需要的且符合条件的记录,这样响应时间会大大的提高,内存开销也可减少。
二、实现的功能:
1、在页面上按指定的格式显示从数据库中取回的数据(用Datagrid控件显示)。
2、对记录进行分页(必须在数据库内进行分页,即传入第几页,每页记录数,就传回己分好页的记录)
3、点击Datagrid标头后以实现重新排序显示,且有点击第一次按降序,点击第二次按升序(不是对已显示的记录进行排序,而是重新到数据库中取出符合条件的并按指定顺序排序的指定页记录)
4、可以通过点击Datagrid的CheckBox框以实现全选和全不选功能,且支持群体操作(如删除,转入等)
三、制约条件
1、数据库表必须有一个关键字段或有一个唯一字段。
四、制作过程(范例):
1、数据库结构:
本范例是用SQLServer自带的数据库Northwind为例,表为Customers
代码编写过程:
1、首先用户新加一个窗体。
2、在窗体上放置一个五个LinkButton控件,并设置ID为:lkbDel,LinkButtonPreview,LinkButtonNext,LinkButtonLast,LinkButtonFirst,设置各控件的Text属性为:“删除”,“首页”,“上一页”,“下一页”,及“尾页”,放置位置如上图;同时在窗体上放一个Datagrid控件,控件的名称为:dgList
3、把dgList控件的AutoSortint属性设为true,AutoGenarateColumes属性设为false,DataKeyField属性设为CustomerID,Width属性设为100%,设置dgList控件的各列如下:
<Columns>
<asp:TemplateColumn>
<HeaderStyleWidth="10px"></HeaderStyle>
<HeaderTemplate>
<INPUTid="chkselectall"type="checkbox"onclick="checkallorno(this)"></asp:CheckBox>
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBoxid="chkselect"runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumnDataField="CustomerID"SortExpression="CustomerID"HeaderText="ID"></asp:BoundColumn>
<asp:BoundColumnDataField="CompanyName"SortExpression="CompanyName"HeaderText="客户名称"></asp:BoundColumn>
<asp:BoundColumnDataField="ContactName"SortExpression="ContactName"HeaderText="联系名称"></asp:BoundColumn>
<asp:BoundColumnDataField="ContactTitle"SortExpression="ContactTitle"HeaderText="职位"></asp:BoundColumn>
<asp:BoundColumnDataField="Phone"SortExpression="Phone"HeaderText="电话"></asp:BoundColumn>
<asp:BoundColumnDataField="Fax"SortExpression="Fax"HeaderText="传真"></asp:BoundColumn>
</Columns>
其中第一列是必须的,其他列可根据情况自己增加或删除。
其中上段代码中点击标头的CheckBox后实现所有的显示项的全选或全不选的功能是由一个javascript的checkallorno(this)函来实现的,具体函数体如下:
<script>
functioncheckallorno(o)
{
vara=o;
while(true)
{
vara=a.parentElement;
if(a==null)
{
break;
}
if(a=="undefined")
{
a=null;
break;
}
if(a.tagName=="TABLE")
{
break;
}
}
if(a!=null)
{
for(i=0;i<a.rows.length;i++)
{
for(j=0;j<a.rows[i].cells[0].children.length;j++)
{
varvar1=a.rows[i].cells[0].children[j];
if(var1.tagName=="INPUT")
{
if(var1.type=="checkbox")
{
var1.checked=o.checked;
}
}
}
}
}
}
</script>
同时设置dgList的SortCommand为dgList_SortCommand()具体实现看原码。
4、设置lkbDel的的Click事件为如下:lkbDel_Click(objectsender,System.EventArgse),当然该事件名你可以随便取名,同时设置LinkButtonPreview,LinkButtonNext,LinkButtonLast,LinkButtonFirst的Click事件为同一个函数(怎样设置事件请看MSDN)。函数名为:dgList_SortCommand(objectsource,System.Web.UI.WebControls.DataGridSortCommandEventArgse);各事件的具体实现请看源代码,在类里放两个变量如下:
//这是每次每页显示的记录数.
privateintRecordPerPage=6;
//这个变量为数据库联接
protectedstringm_cnnstr="datasource=Robert\Robert;initialcatalog=Northwind;Userid=sa;pwd=";
5、在page_Load事件中加入以下代码:
privatevoidPage_Load(objectsender,System.EventArgse)
{
if(!this.IsPostBack)
{
/*this.ViewState["TotalRecord"]
*用于记录总共有多少条记录
**/
this.ViewState["TotalRecord"]=GetTatolRecordNumber();
/*this.ViewState["TotalRecord"]
*用于记录当前显示第几条记录
**/
this.ViewState["CurrentPg"]=1;
/*this.ViewState["Sort"]
*用于存放当前的排序字符串
**/
this.ViewState["Sort"]="";
//对导行栏的状态进行初始化.
setGuide(null);
//第一次显示记录.
ShowData();
}
}
其中GetTatolRecordNumber();是取回总记录数,setGuide(null);是设置分页相关按钮的状态,ShowData();是用来设置dgList控件数据源,这两人函数的具体实现请看源代码。
aspx原码:
<%@Pagelanguage="c#"Codebehind="Pagination.aspx.cs"AutoEventWireup="false"Inherits="SortAndPagination.Pagination"%>
<%@RegisterTagPrefix="iewc"Namespace="Microsoft.Web.UI.WebControls"Assembly="Microsoft.Web.UI.WebControls,Version=1.0.2.226,Culture=neutral,PublicKeyToken=31bf3856ad364e35"%>
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">
<HTML>
<HEAD>
<title>Pagination</title>
<metacontent="MicrosoftVisualStudio.NET7.1"name="GENERATOR">
<metacontent="C#"name="CODE_LANGUAGE">
<metacontent="JavaScript"name="vs_defaultClientScript">
<metacontent="http://schemas.microsoft.com/intellisense/ie5"name="vs_targetSchema">
<script>
functioncheckallorno(o)
{
vara=o;
while(true)
{
vara=a.parentElement;
if(a==null)
{
break;
}
if(a=="undefined")
{
a=null;
break;
}
if(a.tagName=="TABLE")
{
break;
}
}
if(a!=null)
{
for(i=0;i<a.rows.length;i++)
{
for(j=0;j<a.rows[i].cells[0].children.length;j++)
{
varvar1=a.rows[i].cells[0].children[j];
if(var1.tagName=="INPUT")
{
if(var1.type=="checkbox")
{
var1.checked=o.checked;
}
}
}
}
}
}
</script>
</HEAD>
<bodyMS_POSITIONING="GridLayout">
<formid="Form1"method="post"runat="server">
<FONTface="宋体">
<TABLEcellSpacing="1"cellPadding="1"width="100%"border="1">
<tr>
<tdalign="center"colSpan="2"><STRONG><FONTsize="4">关于排序,分页,多条记录选择及删除的范例</FONT></STRONG>
</td>
</tr>
<TR>
<TDalign="right"colSpan="2"><SPANonclick="returnwindow.confirm('你真要删除所选项?')"><asp:linkbuttonid="lkbDel"runat="server">删除</asp:linkbutton></SPAN></TD>
</TR>
<TR>
<TDcolSpan="2"><asp:datagridid="dgList"runat="server"DataKeyField="CustomerID"Width="100%"AllowSorting="True"
AutoGenerateColumns="False"PageSize="20">
<Columns>
<asp:TemplateColumn>
<HeaderStyleWidth="10px"></HeaderStyle>
<HeaderTemplate>
<INPUTid="chkselectall"type="checkbox"onclick="checkallorno(this)"></asp:CheckBox>
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBoxid="chkselect"runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumnDataField="CustomerID"SortExpression="CustomerID"HeaderText="ID"></asp:BoundColumn>
<asp:BoundColumnDataField="CompanyName"SortExpression="CompanyName"HeaderText="客户名称"></asp:BoundColumn>
<asp:BoundColumnDataField="ContactName"SortExpression="ContactName"HeaderText="联系名称"></asp:BoundColumn>
<asp:BoundColumnDataField="ContactTitle"SortExpression="ContactTitle"HeaderText="职位"></asp:BoundColumn>
<asp:BoundColumnDataField="Phone"SortExpression="Phone"HeaderText="电话"></asp:BoundColumn>
<asp:BoundColumnDataField="Fax"SortExpression="Fax"HeaderText="传真"></asp:BoundColumn>
</Columns>
</asp:datagrid></TD>
</TR>
<tr>
<TDalign="right"colSpan="2">
<TABLEid="Table1"cellSpacing="1"cellPadding="1"border="0">
<TR>
<TDnoWrap><asp:linkbuttonid="LinkButtonFirst"runat="server">首页</asp:linkbutton></TD>
<TD>|</TD>
<TDnoWrap><asp:linkbuttonid="LinkButtonPreview"runat="server">上一页</asp:linkbutton></TD>
<TD>|</TD>
<TDnoWrap><asp:linkbuttonid="LinkButtonNext"runat="server">下一页</asp:linkbutton></TD>
<TD>|</TD>
<TDnoWrap><asp:linkbuttonid="LinkButtonLast"runat="server">尾页</asp:linkbutton></TD>
</TR>
</TABLE>
</TD>
</tr>
</TABLE>
</FONT>
</form>
</body>
</HTML>
aspx.cs原码:
usingSystem;
usingSystem.Collections;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Web;
usingSystem.Web.SessionState;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.HtmlControls;
namespaceSortAndPagination
{
///<summary>
///关于排序,分页,多条记录选择及删除的范例
///</summary>
publicclassPagination:System.Web.UI.Page
{
protectedSystem.Web.UI.WebControls.DataGriddgList;
protectedSystem.Web.UI.WebControls.LinkButtonlkbDel;
protectedSystem.Web.UI.WebControls.LinkButtonLinkButtonPreview;
protectedSystem.Web.UI.WebControls.LinkButtonLinkButtonNext;
protectedSystem.Web.UI.WebControls.LinkButtonLinkButtonLast;
protectedSystem.Web.UI.WebControls.LinkButtonLinkButtonFirst;
//这是每次每页显示的记录数.
privateintRecordPerPage=6;
//这个变量为数据库联接
protectedstringm_cnnstr="datasource=devserver-1;initialcatalog=Northwind;Userid=sa;pwd=";
privatevoidPage_Load(objectsender,System.EventArgse)
{
if(!this.IsPostBack)
{
/*this.ViewState["TotalRecord"]
*用于记录总共有多少条记录
**/
this.ViewState["TotalRecord"]=GetTatolRecordNumber();
/*this.ViewState["TotalRecord"]
*用于记录当前显示第几条记录
**/
this.ViewState["CurrentPg"]=1;
/*this.ViewState["Sort"]
*用于存放当前的排序字符串
**/
this.ViewState["Sort"]="";
//对导行栏的状态进行初始化.
setGuide(null);
//第一次显示记录.
ShowData();
}
}
#regionWeb窗体设计器生成的代码
overrideprotectedvoidOnInit(EventArgse)
{
//
//CODEGEN:该调用是ASP.NETWeb窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}
///<summary>
///设计器支持所需的方法-不要使用代码编辑器修改
///此方法的内容。
///</summary>
privatevoidInitializeComponent()
{
this.lkbDel.Click+=newSystem.EventHandler(this.lkbDel_Click);
this.dgList.SortCommand+=newSystem.Web.UI.WebControls.DataGridSortCommandEventHandler(this.dgList_SortCommand);
this.LinkButtonFirst.Click+=newSystem.EventHandler(this.Guid_Click);
this.LinkButtonPreview.Click+=newSystem.EventHandler(this.Guid_Click);
this.LinkButtonNext.Click+=newSystem.EventHandler(this.Guid_Click);
this.LinkButtonLast.Click+=newSystem.EventHandler(this.Guid_Click);
this.Load+=newSystem.EventHandler(this.Page_Load);
}
#endregion
privatevoidShowData()
{
stringorder=this.ViewState["Sort"].ToString();
//构告SQL的排序字符串
if(order!="")
{
order="OrderBy"+order+"";
}
intStartNum=(int)this.ViewState["CurrentPg"]*RecordPerPage;
intintTemNum=StartNum-RecordPerPage;
stringl_SQL="select*from(selecttop"+StartNum.ToString()
+"*fromCustomers"+order+")a"
+"wherea.CustomerIDnotin(Selecttop"+intTemNum.ToString()
+"CustomerIDFromCustomers"+order+")";
System.Data.SqlClient.SqlConnection
l_cnn=newSystem.Data.SqlClient.SqlConnection(this.m_cnnstr);
System.Data.SqlClient.SqlDataAdapter
l_apd=newSystem.Data.SqlClient.SqlDataAdapter(l_SQL,l_cnn);
System.Data.DataTablel_dt=newDataTable("tem");
l_apd.Fill(l_dt);
this.dgList.DataSource=l_dt;
this.dgList.DataBind();
}
///<summary>
///这是用来获取当前总共在数据库中有多少条记录
///</summary>
///<returns>返回记录数</returns>
privateintGetTatolRecordNumber()
{
System.Data.SqlClient.SqlConnection
l_cnn=newSystem.Data.SqlClient.SqlConnection(this.m_cnnstr);
l_cnn.Open();
System.Data.SqlClient.SqlCommand
l_scd=l_cnn.CreateCommand();
l_scd.CommandText="SelectCount(*)FromCustomers";
System.Data.SqlClient.SqlDataReader
l_sdr=l_scd.ExecuteReader();
l_sdr.Read();
//取出总记录数
intl_count=l_sdr.GetInt32(0);
l_cnn.Close();
returnl_count;
}
privatevoiddgList_SortCommand(objectsource,System.Web.UI.WebControls.DataGridSortCommandEventArgse)
{
stringl_CurrentSort=e.SortExpression;
//记录排序字符串
this.ViewState["Sort"]=l_CurrentSort;
foreach(System.Web.UI.WebControls.DataGridColumnl_dgcinthis.dgList.Columns)
{
/*判断是哪一列要进行排序
以便第二次点击时是别外一个顺序
**/
if(l_dgc.SortExpression==l_CurrentSort)
{
l_CurrentSort=l_CurrentSort.Trim();
//这里只是简单的把字段与排序关键字分开,你可以用正则表达式来做会更好
string[]l_arr_str=l_CurrentSort.Split(newchar[]{''});
if(l_arr_str.Length==1)//如果没有后面的排序关键字,则认为它是升序,下次则要改为降序
{
l_dgc.SortExpression=l_arr_str[0]+"desc";
}
else
{
if(l_arr_str[l_arr_str.Length-1].ToLower()=="asc")//如果原来为升序,则改为降序
{
l_dgc.SortExpression=l_arr_str[0]+"desc";
}
else//如果原来为降序,则改为升序
{
l_dgc.SortExpression=l_arr_str[0]+"asc";
}
}
break;//完成排序头更改
}
}
//重新从数据库中取记录并进行排序显示.
try
{
ShowData();
}
catch(Exceptionex)
{
this.Response.Write("<fontcolor=red>"+ex.Message+"</font>");
}
}
privatevoidGuid_Click(objectsender,System.EventArgse)
{
try
{
setGuide(sender);
ShowData();
}
catch(Exceptionex)
{
this.Response.Write("<fontcolor=red>"+ex.Message+"</font>");
}
}
///<summary>
///这是用来显示导行栏中每个元素的状态
///</summary>
///<paramname="sender">表示是按的那一个导行栏元素的按钮,如果不是由导行栏触发,则传null值</param>
privatevoidsetGuide(objectsender)
{
intm_iTotalPage=Convert.ToInt32(System.Math.Ceiling(Convert.ToDouble((int)this.ViewState["TotalRecord"])/Convert.ToDouble(this.RecordPerPage)));
if(m_iTotalPage<(int)this.ViewState["CurrentPg"])
this.ViewState["CurrentPg"]=1;
if(sender==this.LinkButtonFirst)
{
this.ViewState["CurrentPg"]=1;
}
if(sender==this.LinkButtonNext)
{
this.ViewState["CurrentPg"]=(int)this.ViewState["CurrentPg"]+1;
}
if(sender==this.LinkButtonPreview)
{
this.ViewState["CurrentPg"]=(int)this.ViewState["CurrentPg"]-1;
}
if(sender==this.LinkButtonLast)
{
this.ViewState["CurrentPg"]=m_iTotalPage;
}
this.LinkButtonFirst.Enabled=!((int)this.ViewState["CurrentPg"]==1);
this.LinkButtonPreview.Enabled=!((int)this.ViewState["CurrentPg"]==1);
this.LinkButtonLast.Enabled=!((int)this.ViewState["CurrentPg"]==m_iTotalPage);
this.LinkButtonNext.Enabled=!((int)this.ViewState["CurrentPg"]==m_iTotalPage);
}
privatevoidlkbDel_Click(objectsender,System.EventArgse)
{
/*
*下面是用来确定有哪些记录被选种要删除的.
*由于CustomerID是Char类型的,
*所以用如下形式来收集该字符串以便在构建删除语句的时候用
*"'DDFG','CCFE','FDDD'"
**/
stringl_str_id="";
foreach(System.Web.UI.WebControls.DataGridIteml_dglinthis.dgList.Items)
{
//chkselect是每个记录项的ID,记住,这是服务器端的ID,不是客户端的ID.
System.Web.UI.Controll_ct=l_dgl.Cells[0].FindControl("chkselect");
if(l_ct!=null)
{
//下面语句是判断是否记录项的checkbox框初选种
if(((System.Web.UI.WebControls.CheckBox)l_ct).Checked)
{
if(l_str_id=="")
l_str_id="'"+this.dgList.DataKeys[l_dgl.ItemIndex].ToString()+"'";
else
l_str_id+=",'"+this.dgList.DataKeys[l_dgl.ItemIndex].ToString()+"'";
}
}
}
/*
*下面语句是用来删除所选种的ID,"CustomerID"是CustomerID的关键字.
**/
try
{
if(l_str_id!="")
{
System.Data.SqlClient.SqlConnection
l_cnn=newSystem.Data.SqlClient.SqlConnection(this.m_cnnstr);
l_cnn.Open();
System.Data.SqlClient.SqlCommand
l_scd=l_cnn.CreateCommand();
l_scd.CommandText="DeleteFromCustomerswhereCustomerIDin("
+l_str_id+")";
l_scd.ExecuteNonQuery();
}
/*
*删除记录后,要重新计算记录数
*及重新显示记录.
**/
this.ViewState["TotalRecord"]=GetTatolRecordNumber();
setGuide(null);
ShowData();
}
catch(Exceptionex)//这是发生错误后所报的错误
{
this.Response.Write("<fontcolor=red>"+ex.Message+"</font>");
}
}
}
}
做個記錄先。
说明:上面显示的是代码内容。您可以先检查过代码没问题,或修改之后再运行.
|
|