在Asp.Net中,我們使用最多的恐怕就是DataGrid列表控件了。這個控件的功能的卻非常強大,也非常好用。它不但可以實現任意的格式化選擇,而且還可以動態進行分頁、排序、添加按鈕、動態編輯等功能。可以說,DataGrid控件已經實現了我們需要的大部分功能。
DataGrid控件需要通過ViewState來保存控件的狀態的,如果我們關閉了ViewState,即在HTML代碼中使用了EnableViewState="False"屬性,那么,上面的所有有用的功能我們將無法使用。
而ViewState的缺點也是很大的,就是DataGrid會把所有的數據源中的數據存放到ViewState中。我試驗了一下,一個包括5000條記錄的數據庫,如果不在數據庫端控制數據量的話,直接使用Select * From TableName這樣的Sql語句綁定數據的話,一個Asp.Net動態網頁(僅有一個DataGrid控件的測試頁)的ViewState有60k之多。而這樣一個網頁放到公共Web網站,緩慢的網頁下載速度將會使大部分人望而卻步,使用56k貓上網的人就更不要提了,根本無法訪問這樣的網頁,等待的時間將不可忍受。
DataGrid保存在ViewState中的數據分為兩個部分,一部分是保存索引用的,就是DataKeys和DataItems這樣的屬性使用的數據,我們把它稱之為索引數據。還有一部分是DataGrid中數據源的內容,我們稱之為列表數據。
我們如果把實際上無用的列表數據從ViewState中去除,這樣可以大大減小頁面ViewState的數據大小,使用DataGrid時ViewState數據量太大的根本原因就是列表數據存放在ViewState中。
DataGrid的內部工作流程:在數據綁定初始化的時候,生成了一個叫DataGridTable的控件對象,這個對象是繼承System.Web.UI.WebControls.Table控件的。而且這個對象是最先加入(使用Controls.Add()方法)DataGrid中的。而且ViewState中的DataGrid列表數據也是這個控件加入到DataGrid中的。實際上,ViewState中的DataGrid的單元格中的數據實際上是System.Web.UI.WebControls.Table控件的SaveViewState()方法給加進去的。這些數據很多情況下是不需要的。
?
解決方法:在數據綁定的時候,設置DataGrid中DataGridTable控件的EnableViewState屬性為False就可以了。
?
首先在頁面初始化中的InitializeComponent()方法內加入事件的委托:
private void InitializeComponent()
{
??? this.myDataGrid.ItemDataBound +=
new DataGridItemEventHandler(this.myDataGrid_ItemDataBound);
}
然后在myDataGrid_ItemDataBound方法內加入控制代碼:
private void myDataGrid_ItemDataBound(object sender, DataGridItemEventArgs e)
{
??? myDataGrid.Controls[0].EnableViewState = false;
}
使用DataGrid時,把上面的代碼加入,將減小使用DataGrid時ViewState的90%的數據量。而且,DataGrid中許多使用ViewState的功能絲毫不少,豈不是兩全其美?
?
當然,網頁執行第一次時,DataGrid的內容正常顯示,而使用了上面的去除ViewState方法后,頁面如果回發處理,DataGrid的內容將會消失。我才明白DataGrid內DataGridTable把數據存放在ViewState內的用意。微軟的設計是非常嚴謹的,他們的用意就是當使用Page.IsPostBack屬性時,僅訪問一次數據庫就可以永久保持DataGrid的數據(在不離開此頁面的情況下),數據存放的地點就是頁面的ViewState中。這樣頁面回發后,DataGrid就可以從ViewState中重新生成DataGrid的顯示內容,無需訪問數據庫。所以說微軟以犧牲客戶下載的速度(ViewState數據量)來保證服務器的資源,大家都知道頻繁訪問數據庫對服務器的資源消耗很大。
所以,使用上面減少DataGrid的ViewState數據的法子是可行的,但是必須使所有的頁面回發處理都必須進行數據綁定,否則DataGrid無法獲得數據庫內容,也無法獲得ViewState中保存的數據,那么回發后DataGrid將無法顯示任何內容。
?
總結:使用上面減少ViewState的辦法可以大大加快客戶端的下載顯示速度,但是頻繁的數據庫訪問將加大服務器的壓力;使用ViewState可以減輕服務器的壓力,但是又加大了客戶端的下載時間,它們是互相矛盾的。所以開發者要根據實際情況選擇是否使用DataGrid.Controls[0].EnableViewState=false;的法子,如何選擇,大家請自己斟酌。
|