用.net製作排序、分頁解決資料大的問題

來源:互聯網
上載者:User
用.net製作排序、分頁解決資料大的問題

一、概述:

Datagrid在web應用程式中經常用到,但是Datagrid控制項本身提拱的排序,分頁功能對於有著大量記錄的表來說,按它的做法是不現實的,如一個表有20萬記錄,按Datagrid本身的排序和分頁的原理,必須把所有的記錄全部取回,再進行分頁,這對伺服器的記憶體及響應的速度是一個挑戰。本論文提供了這樣一個解決方案,就是只從資料庫中取回你所需要的且合格記錄,這樣回應時間會大大的提高,記憶體開銷也可減少。

二、實現的功能:

1、在頁面上按指定的格式顯示從資料庫中取回的資料(用Datagrid控制項顯示)。

2、對記錄進行分頁(必須在資料庫內進行分頁,即傳入第幾頁,每頁記錄數,就傳回己分好頁的記錄)

3、點擊Datagrid標題後以實現重新排序顯示,且有點擊第一次按降序,點擊第二次按升序(不是對已顯示的記錄進行排序,而是重新到資料庫中取出合格並按指定順序排序的指定頁記錄)

4、可以通過點擊Datagrid的CheckBox框以實現全選和全不選功能,且支援群體操作(如刪除,轉入等)

三、制約條件

1、資料庫表必須有一個關鍵字段或有一個唯一欄位。

四、製作過程(範例):

1、資料庫結構:

本範例是用SQL Server內建的資料庫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>
<HeaderStyle Width="10px"></HeaderStyle>
<HeaderTemplate>
<INPUT id="chkselectall" type="checkbox" onclick="checkallorno(this)"></asp:CheckBox>
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox id="chkselect" runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="CustomerID" SortExpression="CustomerID" HeaderText="ID"></asp:BoundColumn>
<asp:BoundColumn DataField="CompanyName" SortExpression="CompanyName" HeaderText="客戶名稱"></asp:BoundColumn>
<asp:BoundColumn DataField="ContactName" SortExpression="ContactName" HeaderText="聯絡名稱"></asp:BoundColumn>
<asp:BoundColumn DataField="ContactTitle" SortExpression="ContactTitle" HeaderText="職位"></asp:BoundColumn>
<asp:BoundColumn DataField="Phone" SortExpression="Phone" HeaderText="電話"></asp:BoundColumn>
<asp:BoundColumn DataField="Fax" SortExpression="Fax" HeaderText="傳真"></asp:BoundColumn>
</Columns>
其中第一列是必須的,其他列可根據情況自己增加或刪除。
其中上段代碼中點擊標題的CheckBox後實現所有的顯示項目的全選或全不選的功能是由一個javascript的checkallorno(this)函來實現的,具體函數體如下:

<script>
function checkallorno(o)
{
var a=o;
while(true)
{
var a=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++)
{
var var1=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(object sender, System.EventArgs e),當然該事件名你可以隨便取名,同時設定LinkButtonPreview,LinkButtonNext,LinkButtonLast,LinkButtonFirst的Click事件為同一個函數(怎樣設定事件請看MSDN)。函數名為:dgList_SortCommand(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e);各事件的具體實現請看原始碼,在類裡放兩個變數如下:

//這是每次每頁顯示的記錄數.
private int RecordPerPage=6;
//這個變數為資料庫聯結
protected string m_cnnstr="data source=Robert\Robert;initial catalog=Northwind;User id=sa;pwd=";
5、在page_Load事件中加入以下代碼:

private void Page_Load(object sender, System.EventArgs e)
{
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原碼:

<%@ Page language="c#" Codebehind="Pagination.aspx.cs" AutoEventWireup="false" Inherits="SortAndPagination.Pagination" %>
<%@ Register TagPrefix="iewc" Namespace="Microsoft.Web.UI.WebControls" Assembly="Microsoft.Web.UI.WebControls, Version=1.0.2.226, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>Pagination</title>
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
<meta content="C#" name="CODE_LANGUAGE">
<meta content="JavaScript" name="vs_defaultClientScript">
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
<script>
function checkallorno(o)
{
var a=o;

while(true)
{
var a=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++)
{
var var1=a.rows[i].cells[0].children[j];
if(var1.tagName=="INPUT" )
{
if(var1.type=="checkbox")
{
var1.checked=o.checked;
}
}
}
}

}
}
</script>
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<FONT face="宋體">
<TABLE cellSpacing="1" cellPadding="1" width="100%" border="1">
<tr>
<td align="center" colSpan="2"><STRONG><FONT size="4">關於排序,分頁,多條記錄選擇及刪除的範例</FONT></STRONG>
</td>
</tr>
<TR>
<TD align="right" colSpan="2"><SPAN onclick="return window.confirm('你真要刪除所選項?')"><asp:linkbutton id="lkbDel" runat="server">刪除</asp:linkbutton></SPAN></TD>
</TR>
<TR>
<TD colSpan="2"><asp:datagrid id="dgList" runat="server" DataKeyField="CustomerID" Width="100%" AllowSorting="True"
AutoGenerateColumns="False" PageSize="20">
<Columns>
<asp:TemplateColumn>
<HeaderStyle Width="10px"></HeaderStyle>
<HeaderTemplate>
<INPUT id="chkselectall" type="checkbox" onclick="checkallorno(this)"></asp:CheckBox>
</HeaderTemplate>
<ItemTemplate>
<asp:CheckBox id="chkselect" runat="server"></asp:CheckBox>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="CustomerID" SortExpression="CustomerID" HeaderText="ID"></asp:BoundColumn>
<asp:BoundColumn DataField="CompanyName" SortExpression="CompanyName" HeaderText="客戶名稱"></asp:BoundColumn>
<asp:BoundColumn DataField="ContactName" SortExpression="ContactName" HeaderText="聯絡名稱"></asp:BoundColumn>
<asp:BoundColumn DataField="ContactTitle" SortExpression="ContactTitle" HeaderText="職位"></asp:BoundColumn>
<asp:BoundColumn DataField="Phone" SortExpression="Phone" HeaderText="電話"></asp:BoundColumn>
<asp:BoundColumn DataField="Fax" SortExpression="Fax" HeaderText="傳真"></asp:BoundColumn>
</Columns>
</asp:datagrid></TD>
</TR>
<tr>
<TD align="right" colSpan="2">
<TABLE id="Table1" cellSpacing="1" cellPadding="1" border="0">
<TR>
<TD noWrap><asp:linkbutton id="LinkButtonFirst" runat="server">首頁</asp:linkbutton></TD>
<TD>|</TD>
<TD noWrap><asp:linkbutton id="LinkButtonPreview" runat="server">上一頁</asp:linkbutton></TD>
<TD>|</TD>
<TD noWrap><asp:linkbutton id="LinkButtonNext" runat="server">下一頁</asp:linkbutton></TD>
<TD>|</TD>
<TD noWrap><asp:linkbutton id="LinkButtonLast" runat="server">尾頁</asp:linkbutton></TD>
</TR>
</TABLE>
</TD>
</tr>
</TABLE>
</FONT>
</form>
</body>
</HTML>
aspx.cs原碼:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace SortAndPagination
{
/// <summary>
/// 關於排序,分頁,多條記錄選擇及刪除的範例
/// </summary>
public class Pagination : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DataGrid dgList;
protected System.Web.UI.WebControls.LinkButton lkbDel;
protected System.Web.UI.WebControls.LinkButton LinkButtonPreview;
protected System.Web.UI.WebControls.LinkButton LinkButtonNext;
protected System.Web.UI.WebControls.LinkButton LinkButtonLast;
protected System.Web.UI.WebControls.LinkButton LinkButtonFirst;

//這是每次每頁顯示的記錄數.
private int RecordPerPage=6;
//這個變數為資料庫聯結
protected string m_cnnstr="data source=devserver-1;initial catalog=Northwind;User id=sa;pwd=";

private void Page_Load(object sender, System.EventArgs e)
{
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();
}
}

#region Web Form設計器產生的程式碼
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 該調用是 ASP.NET Web Form設計器所必需的。
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// 設計器支援所需的方法 - 不要使用代碼編輯器修改
/// 此方法的內容。
/// </summary>
private void InitializeComponent()
{
this.lkbDel.Click += new System.EventHandler(this.lkbDel_Click);
this.dgList.SortCommand += new System.Web.UI.WebControls.DataGridSortCommandEventHandler(this.dgList_SortCommand);
this.LinkButtonFirst.Click += new System.EventHandler(this.Guid_Click);
this.LinkButtonPreview.Click += new System.EventHandler(this.Guid_Click);
this.LinkButtonNext.Click += new System.EventHandler(this.Guid_Click);
this.LinkButtonLast.Click += new System.EventHandler(this.Guid_Click);
this.Load += new System.EventHandler(this.Page_Load);

}
#endregion

private void ShowData()
{
string order=this.ViewState["Sort"].ToString();
//構告SQL的排序字串
if(order!="")
{
order=" Order By "+order+" ";
}
int StartNum=(int)this.ViewState["CurrentPg"]*RecordPerPage;
int intTemNum=StartNum-RecordPerPage;
string l_SQL="select * from (select top "+StartNum.ToString()
+" * from Customers "+order+") a "
+" where a.CustomerID not in (Select top "+intTemNum.ToString()
+" CustomerID From Customers "+order+")";

System.Data.SqlClient.SqlConnection
l_cnn=new System.Data.SqlClient.SqlConnection(this.m_cnnstr);
System.Data.SqlClient.SqlDataAdapter
l_apd=new System.Data.SqlClient.SqlDataAdapter(l_SQL,l_cnn);
System.Data.DataTable l_dt=new DataTable("tem");
l_apd.Fill(l_dt);

this.dgList.DataSource=l_dt;
this.dgList.DataBind();

}

/// <summary>
/// 這是用來擷取當前總共在資料庫中有多少條記錄
/// </summary>
/// <returns>返回記錄數</returns>
private int GetTatolRecordNumber()
{
System.Data.SqlClient.SqlConnection
l_cnn=new System.Data.SqlClient.SqlConnection(this.m_cnnstr);
l_cnn.Open();
System.Data.SqlClient.SqlCommand
l_scd=l_cnn.CreateCommand();
l_scd.CommandText="Select Count(*) From Customers";
System.Data.SqlClient.SqlDataReader
l_sdr=l_scd.ExecuteReader();
l_sdr.Read();
//取出總記錄數
int l_count=l_sdr.GetInt32(0);
l_cnn.Close();
return l_count;
}

private void dgList_SortCommand(object source, System.Web.UI.WebControls.DataGridSortCommandEventArgs e)
{
string l_CurrentSort=e.SortExpression;
//記錄排序字串
this.ViewState["Sort"]= l_CurrentSort;
foreach(System.Web.UI.WebControls.DataGridColumn l_dgc in this.dgList.Columns)
{
/*判斷是哪一列要進行排序
以便第二次點擊時是別外一個順序
**/
if(l_dgc.SortExpression==l_CurrentSort)
{
l_CurrentSort=l_CurrentSort.Trim();
//這裡只是簡單的把欄位與排序關鍵字分開,你可以用Regex來做會更好
string [] l_arr_str=l_CurrentSort.Split(new char[]{' '});
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(Exception ex)
{
this.Response.Write("<font color=red>"+ex.Message+"</font>");
}
}

private void Guid_Click(object sender, System.EventArgs e)
{
try
{
setGuide(sender);
ShowData();
}
catch(Exception ex)
{
this.Response.Write("<font color=red>"+ex.Message+"</font>");
}
}

/// <summary>
/// 這是用來顯示導行欄中每個元素的狀態
/// </summary>
/// <param name="sender">表示是按的那一個導行欄元素的按鈕,如果不是由導行欄觸發,則傳null值</param>
private void setGuide(object sender)
{
int m_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);
}

private void lkbDel_Click(object sender, System.EventArgs e)
{
/*
* 下面是用來確定有哪些記錄被選種要刪除的.
* 由於CustomerID是Char類型的,
* 所以用如下形式來收集該字串以便在構建刪除語句的時候用
* "'DDFG','CCFE','FDDD'"
* */
string l_str_id="";
foreach(System.Web.UI.WebControls.DataGridItem l_dgl in this.dgList.Items)
{
//chkselect是每個記錄項的ID,記住,這是伺服器端的ID,不是用戶端的ID.
System.Web.UI.Control l_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=new System.Data.SqlClient.SqlConnection(this.m_cnnstr);
l_cnn.Open();
System.Data.SqlClient.SqlCommand
l_scd=l_cnn.CreateCommand();
l_scd.CommandText="Delete From Customers where CustomerID in ("
+l_str_id+")";
l_scd.ExecuteNonQuery();
}
/*
* 刪除記錄後,要重新計算記錄數
* 及重新顯示記錄.
* */
this.ViewState["TotalRecord"]=GetTatolRecordNumber();
setGuide(null);
ShowData();
}
catch(Exception ex)//這是發生錯誤後所報的錯誤
{
this.Response.Write("<font color=red>"+ex.Message+"</font>");
}
}
}
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.