摘要:該文基于在線交互教務(wù)管理系統(tǒng)的開發(fā)經(jīng)驗,利用ASP.NET提供的TreeView控件,結(jié)合SQL Server數(shù)據(jù)庫表,采用深度遞歸遍歷算法實現(xiàn)了動態(tài)導(dǎo)航樹,并對算法進行了性能分析。
關(guān)鍵詞:TreeView;數(shù)據(jù)庫表;遞歸算法; 動態(tài)導(dǎo)航樹
中圖分類號 TP311文獻標(biāo)識碼:A 文章編號:1009-3044(2008)28-0146-03
Achievement of Dynamic Navigation Tree Based on ASP.NET
YAO Dun-hong1,2,CHEN Shu-yu1,JIANG Qi-ming2
(1.School of Software Engineering, ChongQing University, ChongQing 400030, China;2.Department of Computer Science and Technology of Huaihua University, Hunnan 418008, China)
Abstract: This paper on the basis of the development experience of \" Interactive Online Educational Management System \", using TreeView control provide by ASP.NET, combine SQL Server database table, adopt the depth spreading recursion algorithm has been realized dynamic navigating tree, and has carried on the analysis of performance to the algorithm.
Key words: treeView; database table;algorithm; dynamical navigation tree
1 引言
在使用ASP.NET開發(fā)基于WEB的應(yīng)用系統(tǒng)時,用戶經(jīng)常希望用樹狀結(jié)構(gòu)來顯示分類或?qū)哟螖?shù)據(jù),比如網(wǎng)站的樹形導(dǎo)航、管理分類導(dǎo)航等。使用這樣的動態(tài)顯示技術(shù)既簡單又直觀,而且方便用戶訪問。ASP.NET提供的TreeView服務(wù)器控件[1]就是以分層的方式向用戶提供信息的,適用分層的數(shù)據(jù)集、文件夾視圖以及其它類似的數(shù)據(jù)結(jié)構(gòu),可以生成用于顯示分層數(shù)據(jù)的用戶界面。
如何在ASP.NET下實現(xiàn)動態(tài)樹型結(jié)構(gòu)的生成,是一直以來的討論話題,筆者結(jié)合實際開發(fā)經(jīng)驗,現(xiàn)將利用ASP.NET服務(wù)器控件TreeView結(jié)合SQL Server2000數(shù)據(jù)庫設(shè)計動態(tài)樹型結(jié)構(gòu)的設(shè)計與實現(xiàn)總結(jié)如下。
2 動態(tài)導(dǎo)航樹數(shù)據(jù)表及訪問技術(shù)
與動態(tài)樹相對應(yīng)的樹稱之為靜態(tài)樹,靜態(tài)樹的生成雖然比較簡單,不需要編寫太多代碼,但其后續(xù)維護工作比較復(fù)雜。在實際開發(fā)過程中,更好的方法是結(jié)合數(shù)據(jù)庫生成動態(tài)樹,實現(xiàn)動態(tài)綁定顯示節(jié)點及增刪節(jié)點。
2.1 數(shù)據(jù)庫表結(jié)構(gòu)設(shè)計
表1是筆者在開發(fā)在線交互教務(wù)管理系統(tǒng)中所設(shè)計的導(dǎo)航數(shù)據(jù)庫表。表中的每一個元組都包含樹中一個節(jié)點的信息: 主關(guān)鍵字NodeID是結(jié)點在樹中的唯一標(biāo)識; ParentID存放該節(jié)點上級節(jié)點的NodeID,其中根結(jié)點的ParentD設(shè)為0;NodeName用于節(jié)點名稱,在實際應(yīng)用中可用于存放希望顯示在網(wǎng)頁上的結(jié)點信息;NodeURL存放節(jié)點鏈接地址;Pic為顯示在每個節(jié)點前的圖形文件地址。
2.2 TreeView控件與數(shù)據(jù)庫的連接
數(shù)據(jù)庫表建好后就可在VS2005中創(chuàng)建樹形結(jié)構(gòu)頁面tree.aspx,并從工具框中拖放一個樹形控件,然后的工作就是對其節(jié)點數(shù)據(jù)的添加和綁定及控件事件、效果的添加和設(shè)定。
考慮到系統(tǒng)代碼的可重用性[3],按照三層結(jié)構(gòu)進行創(chuàng)建,所以數(shù)據(jù)層單獨列出并作為一個類[4]進行創(chuàng)建。如DBclass.cs類,其類圖如圖1所示。
其中GetConnection()方法的定義如下:
public static SqlConnection GetConnection()
{ //獲取數(shù)據(jù)連接語句,并創(chuàng)建數(shù)據(jù)庫連接對象
String conn = ConfigurationManager.AppSettings[\"sqlconn\"].ToString();
SqlConnection myConn;
myConn = new SqlConnection(conn);
return myConn;
}
另外GetUrl()是根據(jù)NodeID標(biāo)識號取得節(jié)點對應(yīng)URL的方法也在此一并定義。
2.3 數(shù)據(jù)庫訪問技術(shù)
ASP.NET中對數(shù)據(jù)庫的訪問是通過ADO.NET(動態(tài)數(shù)據(jù)對象)上的ManagedProvide所提供的API來實現(xiàn)的,包括OLEBD和ODBC所支持的數(shù)據(jù)庫[2]。SqlDataAdapter是DataSet和SQL Server之間的橋接器,用于檢索和保存數(shù)據(jù)。SqlDataAdapter通過對數(shù)據(jù)源使用適當(dāng)?shù)腡ransact-SQL語句映射Fill(它可更改DataSet中的數(shù)據(jù)以匹配數(shù)據(jù)源中的數(shù)據(jù))和Update(它可更改數(shù)據(jù)源中的數(shù)據(jù)以匹配DataSet中的數(shù)據(jù))來提供這一橋接。
首先我們建立Tree類并在類中作如下的定義:
protected SqlConnection myConn;
protected SqlDataAdapter myAdapter;
protected DataSet data;
protected string query;
然后在Tree類中定義一個CreateDataSet方法來建立與數(shù)據(jù)庫的訪問:
public DataSet CreateDataSet()
{
query = \"select * from sysfuncrights\";
myAdapter = new SqlDataAdapter(query, myConn);
data = new DataSet();
myAdapter.Fill(data, \"query\");
return data;
}
3 深度遍歷遞歸算法
3.1 導(dǎo)航目錄樹的深度遍歷思想
從sysfuncrights數(shù)據(jù)庫表結(jié)構(gòu)我們可以看出,該表中有一個稱為根的結(jié)點,根結(jié)點下可以有多個子結(jié)點(即一級樹目錄),而每個一級結(jié)點下又可有若干個子結(jié)點(二級樹目錄),子結(jié)點下又可有子結(jié)點(三級樹目錄)…,這樣我們可以把sysfuncrights表中記錄之間的關(guān)系理解為一個無環(huán)路的非連通圖G。
假設(shè)給定圖G的初態(tài)是所有頂點均未曾訪問過。在G先選根結(jié)點v為初始出發(fā)點(源點),則深度優(yōu)先遍歷可定義如下:首先訪問出發(fā)點v,并將其標(biāo)記為已訪問過;然后依次從v出發(fā)搜索v的每個鄰接點w。若w未曾訪問過,則以w為新的出發(fā)點繼續(xù)進行深度優(yōu)先遍歷,直至圖中所有和源點v有路徑相通的頂點(亦稱為從源點可達的頂點)均已被訪問為止。若此時圖中仍有未訪問的頂點,則另選一個尚未訪問的頂點作為新的源點重復(fù)上述過程,直至圖中所有頂點均已被訪問為止[5]。
3.2 深度遍歷遞歸算法的實現(xiàn)
以下是在Tree類中利用深度遍歷遞歸算法定義InitTree方法創(chuàng)建導(dǎo)航目錄樹,其參數(shù)可從上面所獲得的data數(shù)據(jù)集。
//從DataSet中取數(shù)據(jù)建樹
//從根節(jié)點開始遞歸調(diào)用顯示子樹
public void InitTree(TreeNodeCollection Nds, string parentId)
{
TreeNode NewNode;
//data為存儲建樹數(shù)據(jù)信息的數(shù)據(jù)集
//用父節(jié)點進行篩選數(shù)據(jù)集中信息
DataRow[] rows = data.Tables[0].Select(\"parentId='\" + parentId + \"'\");
foreach (DataRow row in rows)//遍歷當(dāng)前的所有子節(jié)點
{
NewNode = newTreeNode(row[\"NodeName\"].ToString(), row[\"NodeId\"].ToString(), row[\"NodeURL\"].ToString());
NewNode.NavigateUrl = row[\"NodeURL\"].ToString();//取得節(jié)點導(dǎo)航路徑
NewNode.ImageUrl = row[\"pic\"].ToString();//取得節(jié)點所對應(yīng)的圖形路徑
Nds.Add(NewNode);//將節(jié)點添加到TreeView的節(jié)點集合中
InitTree(NewNode.ChildNodes, row[\"NodeId\"].ToString());//遞歸調(diào)用
TreeView1.Target = \"wdcontent\";
}
}
4 結(jié)果分析
我們知道,對于圖的深度優(yōu)先算法的時間復(fù)雜度為O(n2)[6],這就取決于n規(guī)模的大小,如果在開發(fā)的應(yīng)用系統(tǒng)中導(dǎo)航目錄樹節(jié)點n不太大的情況下,其效果是不錯的。筆者利用這種算法思想開發(fā)在線交互教務(wù)管理系統(tǒng)得到的導(dǎo)航目錄樹基本滿足了問題需求,運行結(jié)果理想,如圖2所示。
5 結(jié)論
通過介紹建立動態(tài)導(dǎo)航樹的數(shù)據(jù)表、存儲到DataSet對象中,并以所獲得的data作為參數(shù)使用遞歸算法生成導(dǎo)航樹,闡述了在ASP.NET中使用TreeView控件和數(shù)據(jù)庫技術(shù)創(chuàng)建動態(tài)導(dǎo)航樹的具體實現(xiàn)方法和步驟。這種依賴于數(shù)據(jù)庫生成的導(dǎo)航樹隨著數(shù)據(jù)源的改變樹結(jié)構(gòu)隨之轉(zhuǎn)換,避免了靜態(tài)導(dǎo)航樹下數(shù)據(jù)源經(jīng)常性改變而不得不頻繁修改程序代碼帶來的麻煩,使得在網(wǎng)頁上實現(xiàn)導(dǎo)航樹和在窗體程序中一樣方便。
參考文獻:
[1] 施燕妹,陳培,陳發(fā)吉,等. C#語言程序設(shè)計教程[M].北京:中國水利水電出版社,2004.
[2] [美]KLAUS MICHELSEN,c# PRIMER PLUS(中文版)[M].北京:人民郵電出版社,2002.
[3] 肖漢.基于可重用構(gòu)件的軟件開發(fā)模式研究[J].微電子學(xué)與計算機,2007(1):178-181.
[4] [美]Wendy B,Michael B.UML與Rational Rose 2002從入門到精通[M].北京:電子工業(yè)出版社,2002.
[5] 嚴(yán)蔚敏,吳偉民.數(shù)據(jù)結(jié)構(gòu)[M].北京:清華大學(xué)出版社,2002.
[6] 鄧芳.關(guān)于遞歸算法時間復(fù)雜度分析的探討[J].浙江萬里學(xué)院學(xué)報,2005(4):24-27.