我现在做的窗口用第三方控件AdvTree(树形节点)和数据库中的院系名,专业名和班级名进行绑定,其中院系名为一级节点,专业名为二级节点,班级名为三级节点.,院系名,专业名和班级名这几个加起来的数据有1670条的,调试的时候这个窗口弹出来要10秒左右,总是觉得很慢,该怎么办?   (老师不能让我们用数据集,要全用代码实现)

解决方案 »

  1.   

    我一般是用这种方法的,请问哪里可以再改进一下?
    //定义数据行yx(院系行)为实例JieMian的方法返回的第零个表(院系表)的行集合中的某行,并循环读取,每读取一行做以下事情
                foreach (DataRow yx in JieMian.Select_JieMian().Tables[0].Rows)
                {
                    //定义出局部字符串变量YuanXi(院系),并赋值为读取行的第一列数值(院系名称)
                    string YuanXi = yx[1].ToString().Trim();                //实例化一个节点并取名为YxNameNode(院系名节点)
                    DevComponents.AdvTree.Node YxNameNode = new DevComponents.AdvTree.Node();                //定义该节点的Text为YuanXi(院系名称)
                    YxNameNode.Text = YuanXi;                //定义该节点的Name为读取行的第0列数值(院系代码)
                    YxNameNode.Name = yx[0].ToString().Trim();                //定义该节点的默认图标为第9个图标(合上的书本)
                    YxNameNode.ImageIndex = 9;                //定义该节点的展开时图标为第10个图标(打开的书本)
                    YxNameNode.ImageExpandedIndex = 10;                //向树形控件advTree1中追加一级节点YxNameNode(院系)
                    advTree1.Nodes.Add(YxNameNode);                //定义数据行zy(专业行)为实例JieMian的方法返回的第1个表(专业表)的行集合中的某行,并循环读取,每读取一行做以下事情
                    foreach (DataRow zy in JieMian.Select_JieMian().Tables[1].Rows)
                    {
                        //当节点YxNameNode(院系名称节点)的Name(院系代码)与读取行的第四列的值(院系代码)相同时
                        if (YxNameNode.Name == zy[4].ToString().Trim())
                        {
                            //定义出局部字符串变量ZhuanYe(专业),并赋值为读取行的第一列数值(年级)+第二列数值(专业名称)+第三列数值(学制)
                            string ZhuanYe = zy[1].ToString().Trim() + "级" + zy[2].ToString().Trim() + "学制:" + zy[3].ToString().Trim();                        //实例化一个节点并取名为YxNameNode(专业名节点)
                            DevComponents.AdvTree.Node ZyNameNode = new DevComponents.AdvTree.Node();                        //定义该节点的Text为ZhuanYe(专业名称)
                            ZyNameNode.Text = ZhuanYe;                        //定义该节点的Name为读取行的第0列数值(专业代码)
                            ZyNameNode.Name = zy[0].ToString().Trim();                        //定义该节点的默认图标为第9个图标(合上的书本)
                            ZyNameNode.ImageIndex = 9;                        //定义该节点的展开时图标为第10个图标(打开的书本)
                            ZyNameNode.ImageExpandedIndex = 10;                        //向一级节点YxNameNode(院系节点)追加二级节点ZyNameNode(专业名节点)
                            YxNameNode.Nodes.Add(ZyNameNode);                        //定义数据行bj(班级行)为实例JieMian的方法返回的第2个表(班级表)的行集合中的某行,并循环读取,每读取一行做以下事情
                            foreach (DataRow bj in JieMian.Select_JieMian().Tables[2].Rows)
                            {
                                //当节点ZyNameNode(专业名节点)的Name(专业代码)与读取行的第2列的值(专业代码)相同时
                                if (ZyNameNode.Name == bj[2].ToString().Trim())
                                {
                                    //定义出局部字符串变量BanJi(班级名称),并赋值为读取行的第一列数值(班级名称)
                                    string BanJi = bj[1].ToString().Trim();                                //实例化一个节点并取名为BjNameNode(班级名节点)
                                    DevComponents.AdvTree.Node BjNameNode = new DevComponents.AdvTree.Node();                                //定义该节点的Text为BanJi(班级名称)
                                    BjNameNode.Text = BanJi;                                //定义该节点的Name为读取行的第0列数值(班级代码)
                                    BjNameNode.Name = bj[0].ToString().Trim();                                //定义该节点的默认图标为第9个图标(合上的书本)
                                    BjNameNode.ImageIndex = 9;                                //定义该节点的点击时图标为第10个图标(打开的书本)
                                    BjNameNode.ImageMouseOverIndex = 10;                                //向二级节点ZyNameNode(专业名节点)追加三级节点BjNameNode(班级名节点)
                                    ZyNameNode.Nodes.Add(BjNameNode);
                                }
                            }                    }
                    }            }
      

  2.   

    我现在知道为什么读取那么慢了,问题都解决了~~因为我在自定义类中调用查询表存储过程后,都把那个通道销毁了,这不知道是不是原因之一;现在我先定义3个行集合分别把自定义类的实例中方法返回的院系,专业,班级三个表的行都装起来,然后foreach中都改用定义的三个集合,这样的话可能访问数据库的次数少了,一下子读取出来了~
      

  3.   

    我的建议:1670 条记录一次性读出来,然后再用LINQ组合成TREENODE,这样就只有一次数据库访问了。
    LINQ在内存对象上查询也很快。
      

  4.   

    可以用递归的方法  大概的举个例子
    第一种填充时展开节点
    TreeNode tempnd;
        //定义一个数据集
        public DataTable table = new DataTable();
        //填充单元
        public DataSet ds = new DataSet();
        List<int> HFunid = new List<int>();
        string SqlConStr = "server=.;uid=sa;pwd=;database=exampletest;";
        string sqlstr = "";
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                List<int> a = new List<int>();
                a.Add(2);
                HFunid = a;
                filldata();
            }
        }
        private void filldata()
        {
            SqlConnection con = new SqlConnection(SqlConStr);
            sqlstr = "select id,name,parentid from filltree";
            SqlDataAdapter sda = new SqlDataAdapter(sqlstr, con);
            sda.Fill(ds);
            InitTree(TreeView1.Nodes, "0");
        }    //填充时展开节点
        private void InitTree(TreeNodeCollection nds, string parent)
        {
            DataRow[] rows = ds.Tables[0].Select("parentid='" + parent + "'");
            foreach (DataRow row in rows)       //递归算法来实现树控件的动态填充
            {
                tempnd = new TreeNode();
                tempnd.Value = row["id"].ToString();
                tempnd.Text = row["name"].ToString();
                //判断check是否为真
                for (int i = 0; i < HFunid.Count; i++)
                {
                    if (Convert.ToInt32(tempnd.Value) == HFunid[i])
                    {
                        tempnd.Checked = true;
                    }
                }
                nds.Add(tempnd);
                InitTree(tempnd .ChildNodes, tempnd.Value);
            }
        }//填充时不展开节点
    DataSet ds = new DataSet();
        string sqlstr = "";
        string SqlConStr = "server=.;uid=sa;pwd=;database=exampletest;";
        
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                filldata();
            }
        }
        //填充tree
        private void filldata()
        {
            SqlConnection con = new SqlConnection(SqlConStr);
            sqlstr = "select id,name,parentid from filltree where parentid='0'";
            SqlDataAdapter sda = new SqlDataAdapter(sqlstr, con);
            sda.Fill(ds);
            InitTree(TreeView1.Nodes, "0");
        }
        //加载时填充根节点,判断是否有子节点
        private void InitTree(TreeNodeCollection nds, string parent)
        {
            SqlConnection con = new SqlConnection(SqlConStr);
            TreeNode tempnd;
            DataRow[] rows = ds.Tables[0].Select("parentid='" + parent + "'");
            foreach (DataRow row in rows)       //递归算法来实现树控件的动态填充
            {
                tempnd = new TreeNode();
                tempnd.Value = row["id"].ToString();
                tempnd.Text = row["name"].ToString();
                sqlstr = "select id,name,parentid from filltree where parentid='" + row["id"].ToString() + "'";
                SqlCommand com = new SqlCommand(sqlstr,con);
                con.Open();
                int count = 0;
                if (com.ExecuteScalar() != null)
                {
                    count = int.Parse(com.ExecuteScalar().ToString());
                }
                con.Close();
                if (count > 0)
                {
                    tempnd.PopulateOnDemand = true;//树前面的加号属性
                    tempnd.Expanded = false;//是否展开
                }
                nds.Add(tempnd);
                //InitTree(tempnd.ChildNodes, tempnd.Value);
                count = 0;
            }
        }
        //加号展开事件
        protected void TreeView1_TreeNodePopulate(object sender, TreeNodeEventArgs e)
        {
            int depid = int.Parse(e.Node.Value);
            SqlConnection con = new SqlConnection(SqlConStr);
            if (depid != 0)
            {
                sqlstr = "select id,name,parentid from filltree where parentid='" + depid + "'";
                SqlDataAdapter sda = new SqlDataAdapter(sqlstr, con);
                sda.Fill(ds);
                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    TreeNode node = new TreeNode();
                    node.Text = ds.Tables[0].Rows[i][1].ToString();
                    node.Value = ds.Tables[0].Rows[i][0].ToString();
                    if (ds.Tables[0].Rows.Count > 0)
                    {
                        node.PopulateOnDemand = true;
                        node.Expanded = false;
                    }
                    sqlstr = "select id,name,parentid from filltree where parentid='" + ds.Tables[0].Rows[i][0].ToString() + "'";
                    SqlCommand cmd = new SqlCommand(sqlstr, con);
                    con.Open();
                    if (cmd.ExecuteScalar() != null)
                    {
                        node.PopulateOnDemand = true;
                        node.Expanded = false;
                    }
                    else
                        node.PopulateOnDemand = false;
                    e.Node.ChildNodes.Add(node);
                    con.Close();
                }
            }
        } 
      

  5.   

    有没有发现使用DotNetBar树形结构的时候,引起内存溢出的现象