首页  ·  知识 ·  云计算
asp/asp.net中遍历树型结构
jiny-z  http://jiny-z.cnblogs.com/  综合  编辑:dezai  图片来源:网络
数据库:SqlServer2000表:tree表结构:

数据库:SqlServer2000
:tree
表结构

 

算法:使用递归实现

======================================
asp代码:

<%@ Language = VBScript%>
<%Option Explicit%>
<%
Dim oConn, sSql
Call DBConnBegin()

Dim sTableName
Dim nCurrent, nLen, aTree()
sTableName = "tree"
nCurrent = 1
nLen = GetRescordCount()

ReDim aTree(nLen)

Call GetPowerName(0)
'Dim i
'For i = 1 To nLen
    'Response.Write aTree(i) & "
"
'Next
Call DBConnEnd()

Function  GetRescordCount()
    GetRescordCount = oConn.Execute("select count(id) from " & sTableName)(0)
End Function

Sub GetPowerName(s_Id)
    Dim n_ParentId, j, oRs
    Set oRs = Server.CreateObject( "ADODB.Recordset" )
    sSql = "select id,PowerName,Layer from " & sTableName & " where ParentId=" & s_Id
    oRs.Open sSql, oConn, 0, 1
    Do While Not oRs.Eof
        For j = 1 To oRs("Layer")
            response.write "    "
        Next
        aTree(nCurrent) = oRs("PowerName")
        response.write aTree(nCurrent) & "
"
        nCurrent = nCurrent + 1
        n_ParentId = oRs("id")
        Call GetPowerName(n_ParentId)
        oRs.MoveNext
    Loop
    oRs.Close
    Set oRs = Nothing
End Sub

Sub DBConnBegin()
    ' 如果数据库对象已打开,不要再打开
    If IsObject(oConn) = True Then Exit Sub

    ' 你可以不需要打开数据库连接对象而直接打开记录集对象,但如果你需要打开多个记录集对象的话,效率是很低的。
    ' 如果你不创建一个数据库连接对象,ADO会在每个记录集打开时自动创建一个新的数据库连接对象,就算你用的是相同的SQL语句。
    Set oConn = Server.CreateObject("ADODB.Connection")

    On Error Resume Next

    'Provider=SQLOLEDB.1;Server=(local);Initial Catalog =cx_soft;Integrated Security=SSPI;
    'Provider=SQLOLEDB.1;Server=(local);Initial Catalog =cx_soft;Trusted_Connection=yes;
    oConn.Open "Provider=sqloledb.1;Data Source=(local);Initial Catalog=AspNetTest;User Id=sa;Password=;"
   
    If Err.Number > 0 Then
        ' 完全地退出正在运行的脚本
        Response.End
    End If

    ' 创建一个记录集
   
End Sub

Sub DBConnEnd()
    On Error Resume Next
    oRs.Close
    Set oRs = Nothing
    oConn.Close
    Set oConn = Nothing
End Sub
%>


asp.net代码:
(请注意:asp.net1.1中用同一个Connection,在前一个DataReader没有Close情况下再创建DataReader会出现错误提示:已有打开的与此连接相关联的 DataReader,必须首先将它关闭
我的做法是每次都创建一个Connection,很浪费资源,不知道有没其他好办法.
)
  1using System;
  2using System.Collections;
  3using System.ComponentModel;
  4using System.Data;
  5using System.Drawing;
  6using System.Web;
  7using System.Web.SessionState;
  8using System.Web.UI;
  9using System.Web.UI.WebControls;
 10using System.Web.UI.HtmlControls;
 11using System.Data.SqlClient;
 12
 13namespace AspNetTest.Common
 14{
 15    /**////


 16    /// tree 的摘要说明。
 17    ///

 18
 19    public class tree : System.Web.UI.Page
 20    {
 21        private string tablename = "tree";
 22        int current = 0;
 23        int len = 0;
 24        string[] arrPowerName;
 25        string ConnectionString;
 26        public tree()
 27        {
 28            ConnectionString = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"];
 29            len = GetRecordCount();
 30            arrPowerName = new string[len];
 31        }
 32        private void Page_Load(object sender, System.EventArgs e)
 33        {
 34           
 35            GetPowerName(0);
 36            //CloseDbConnection();
 37            //ResponseArray();
 38            // 在此处放置用户代码以初始化页面
 39        }
 40        private void GetPowerName(int _ParentId)
 41        {
 42            int Id;
 43            string PowerName;
 44            string sql = "select Id,PowerName,Layer from " + tablename + " where ParentId=" + _ParentId;
 45            try
 46            {
 47                SqlConnection conn = new SqlConnection(ConnectionString);
 48                conn.Open();
 49                SqlCommand cmd = new SqlCommand(sql, conn);
 50                SqlDataReader dr = cmd.ExecuteReader();
 51                while(dr.Read())
 52                {   
 53                    for(int j=0; j 54                    {
 55                        Response.Write("    ");
 56                    }
 57                    PowerName = dr["PowerName"].ToString();
 58                    Response.Write(PowerName + "
");
 59                    arrPowerName[current++] = PowerName;
 60                    Id = int.Parse(dr["Id"].ToString());
 61                    GetPowerName(Id);
 62                }
 63                dr.Close();
 64                conn.Close();
 65            }
 66            catch(Exception ex)
 67            {
 68                Response.Write(ex.ToString());
 69            }
 70        }
 71        private void ResponseArray()
 72        {
 73            int i;
 74            for(i=0; i 75            {
 76                Response.Write(arrPowerName[i] + "
");
 77            }
 78        }
 79        private void CloseDbConnection()
 80        {
 81            //conn.Close();
 82        }
 83        private int GetRecordCount()
 84        {
 85            SqlConnection conn = new SqlConnection(ConnectionString);
 86            string sql = "select count(id) from " + tablename;
 87            conn.Open();
 88            SqlCommand cmd = new SqlCommand(sql, conn);
 89            int count = int.Parse(cmd.ExecuteScalar().ToString());
 90            conn.Close();
 91            return count;
 92        }
 93       
 94        Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
 95        override protected void OnInit(EventArgs e)
 96        {
 97            //
 98            // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
 99            //
100            InitializeComponent();
101            base.OnInit(e);
102        }
103       
104        /**////
105        /// 设计器支持所需的方法 - 不要使用代码编辑器修改
106        /// 此方法的内容。
107        ///

108        private void InitializeComponent()
109        {   
110            this.Load += new System.EventHandler(this.Page_Load);
111
112        }
113        #endregion
114    }
115}
116

遍历结果:

 

代码下载:

asp代码:/Files/jiny-z/tree(asp).rar
asp.net代码:/Files/jiny-z/tree(asp.net).rar



*********************************************************
根据chill ,flower.b的提示,修改了代码。
原来:asp/asp.net代码中都是在数据集中循环,效率较低.。
现在:asp代码改为在数组中循环,asp.net代码改为在DataTable中循环。
*********************************************************

asp代码:
<%@ Language = VBScript%>
<%Option Explicit%>
<%
Dim oConn, oRs, sSql
Dim aTree
Call FillArrayFromRs()
Call blTreeArray(0)

Sub FillArrayFromRs()
    Dim s_TableName
    s_TableName = "tree"
    Call DBConnBegin()
    Set oRs = Server.CreateObject( "ADODB.Recordset" )
    sSql = "select Id,PowerName,Layer,ParentId from " & s_TableName
    oRs.Open sSql, oConn, 0, 1
    aTree = oRs.GetRows()
    'response.write ubound(aTree, 2)
    oRs.Close
    Call DBConnEnd()
End Sub

Sub blTreeArray(n_ParentId)
    Dim row, rows
    Dim n_NextParentId
    Dim n_Space
    rows = UBound(aTree, 2)
    for row = 0 To rows
        If aTree(3, row) = n_ParentId Then
            for n_Space = 1 To aTree(2, row)
                Response.Write "    "
            Next
            Response.Write aTree(1, row) & "
"
            n_NextParentId = aTree(0, row)
            blTreeArray(n_NextParentId)
        End If
    Next
End Sub


Sub DBConnBegin()
    ' 如果数据库对象已打开,不要再打开
    If IsObject(oConn) = True Then Exit Sub

    ' 你可以不需要打开数据库连接对象而直接打开记录集对象,但如果你需要打开多个记录集对象的话,效率是很低的。
    ' 如果你不创建一个数据库连接对象,ADO会在每个记录集打开时自动创建一个新的数据库连接对象,就算你用的是相同的SQL语句。
    Set oConn = Server.CreateObject("ADODB.Connection")

    On Error Resume Next

    'Provider=SQLOLEDB.1;Server=(local);Initial Catalog =cx_soft;Integrated Security=SSPI;
    'Provider=SQLOLEDB.1;Server=(local);Initial Catalog =cx_soft;Trusted_Connection=yes;
    oConn.Open "Provider=sqloledb.1;Data Source=(local);Initial Catalog=AspNetTest;User Id=sa;Password=;"
   
    If Err.Number > 0 Then
        ' 完全地退出正在运行的脚本
        Response.End
    End If

    ' 创建一个记录集
   
End Sub

Sub DBConnEnd()
    On Error Resume Next
    oRs.Close
    Set oRs = Nothing
    oConn.Close
    Set oConn = Nothing
End Sub

 


%>
asp.net代码:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
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 AspNetTest.Common
{
    /**////


    /// tree_DataTable 的摘要说明。
    ///

    
    public class tree_DataTable : System.Web.UI.Page
    {
        private DataTable dtPowerTree = new DataTable();
        const string tablename = "tree";
        private void Page_Load(object sender, System.EventArgs e)
        {
            FillTreeDataTable();
            blTreeDataTable(0);
            dtPowerTree.Clear();           
            // 在此处放置用户代码以初始化页面
        }
        private void FillTreeDataTable()
        {
            string ConnectionString = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"];
            SqlConnection conn = new SqlConnection(ConnectionString);
            SqlDataAdapter da = new SqlDataAdapter("select Id,PowerName,Layer,ParentId from " + tablename, conn);
            da.Fill(dtPowerTree);
        }
        private void blTreeDataTable(int _ParentId)
        {
            string filter = "ParentId=" + _ParentId;
            string sort = "Id ASC";
            DataRow[] drs = dtPowerTree.Select(filter, sort);
            for(int i=0; i            {
                if(Convert.ToInt32(drs[i][3]) == _ParentId)
                {
                    int Id = Convert.ToInt32(drs[i][0]);
                    string PowerName = drs[i][1].ToString();
                    int Layer = Convert.ToInt32(drs[i][2]);
                    for(int space=1; space<=Layer; space++)
                    {
                        Page.Response.Write("    ");
                    }
                    Page.Response.Write(PowerName + "
");
                    blTreeDataTable(Id);
                }
            }
        }
        Web 窗体设计器生成的代码#region Web 窗体设计器生成的代码
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
            //
            InitializeComponent();
            base.OnInit(e);
        }
       
        /**////
        /// 设计器支持所需的方法 - 不要使用代码编辑器修改
        /// 此方法的内容。
        ///

        private void InitializeComponent()
        {   
            this.Load += new System.EventHandler(this.Page_Load);

        }
        #endregion
    }
}

本文作者:jiny-z 来源:http://jiny-z.cnblogs.com/
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读