另外我将数据库中的表结构贴出来如下:
表名:ICBOMGROUP
FInterID(BOM内码) FParentID(父BOM内码) FName(名称) FNumber(产品代码)
1039 0 产品 0
2296 0 喷印机壳 1
6497 0 丝印彩盒 2
7035 0 外发加工 3
1041 1039 VGA电视盒 01
1071 1041 TV3488B系列 01.01
1140 1071 TV2188EBOM 01.01.01
1144 1140 普通订单 01.01.01.01
1146 1144 TV2188E 中文BOM 01.01.01.01.01
1145 1140 特殊订单 01.01.01.02
1129 1039 XGA电视盒 02
1199 1129 TV5811T系列 02.02
1212 1199 TV5811BOM 02.02.01
2297 2296 机壳-上盖 1.01
2308 2297 GM998 1.01.01
2312 2308 GM998上盖 灰色 1.01.01.01
7039 7035 支架组件 3.01
7040 7039 PD1048 3.01.01
7172 7040 PD1048支架组件 3.01.01.01
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace WindowsFormsApplication17
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TreeView tv = new TreeView();
tv.AfterSelect += new TreeViewEventHandler(tv_AfterSelect);
tv.Dock = DockStyle.Fill;
this.BuildTree(tv.Nodes, 0);
this.Controls.Add(tv);
}
private void tv_AfterSelect(object sender, TreeViewEventArgs e)
{
// 选择节点后,获取当前节点的信息
// 你可以将下列信息赋给你对应的控件
DataRow row = (DataRow)e.Node.Tag;
Int32 FInterID = (Int32)row["FInterID"];
Int32 ParentId = (Int32)row["FParentID"];
String FName = (String)row["FName"];
}
private DataTable fSampleDataSource;
public DataTable SampleDataSource
{
get //这一段是我连接本人数据的代码
{
SqlConnection thisconnection = new SqlConnection("server=(local);database=GADMEIERP;Integrated Security=true;");
SqlCommand cmd = thisconnection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select FInterID,FParentID,FName,FNumber from ICBOMGROUP";
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
DataSet ds = new DataSet();
adapter.Fill(ds, "ICBOMGROUP");
this.fSampleDataSource = ds.Tables[0];
return fSampleDataSource;
}
}
/// <summary>
/// 创建目录和文件树
/// </summary>
/// <param name="fNodes"></param>
/// <param name="fPath"></param>
public void BuildTree(TreeNodeCollection fNodes, Int32 fParentId)
{
foreach (DataRow row
in this.SampleDataSource.Select(String.Format("FParentID = {0}", fParentId)))
{
TreeNode node = new TreeNode();
node.Text = row["FName"].ToString();
node.Tag = row;
// 递归创建子节点
this.BuildTree(node.Nodes, (Int32)row["FInterID"]);
fNodes.Add(node);
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
在C#FORM界面中,要求有一个treeview控件,根据表结构,生成根结点和子结点:
比如说FParentID为0,为一阶,再根据父节点和子节点依次生成下面的结点,例:
0(产品)
01(VGA电视盒)
01.01(TV3488B系列)
01.01.01(TV2188E BOM)
01.01.01.01(普通订单)
01.01.01.02(特殊订单)
省略了
请高手指点下....连接datagridview控件的语句,偶学习...因为没看过高级编程,摸着石头过河,快淹死偶了...
20 个解决方案
#1
题目:树型BOM结构递归问题
问题:连接datagridview控件的语句?
问题:连接datagridview控件的语句?
#2
先只求根结点,加到树上,然后在单击的时候,展开下层,这样能提高效率,防止一次性加载时间过长,另外代码也好写。在点击树结点时,根据树结点属性,如ID得到其所有子结点的数据,并将其加载到表格中。
#3
先获取FParentID(父BOM内码) = 0的做为根节点.
然后使用循环逐一获取某根节点的各级节点.
C#不会,帮顶.
然后使用循环逐一获取某根节点的各级节点.
C#不会,帮顶.
#4
#5
如果是SQL,参考如下:
/*
标题:查询所有*节点及其子节点的例
地址:http://topic.csdn.net/u/20090323/21/63a91f51-c4df-464d-ba18-64343deb4e3a.html
作者:爱新觉罗·毓华(十八年风雨,守得冰山雪莲花开)
时间:2009-03-23
地点:广东深圳
*/
[code=SQL]create table Area (id int identity,Name varchar(10) ,order_by int ,father_ID int )
insert into area values('广东省',2,0)
insert into area values('四川省',2,0)
insert into area values('湖北省',2,0)
insert into area values('东莞市',1,1)
insert into area values('广州市',1,1)
insert into area values('天河区',0,5)
insert into area values('绵阳市',1,2)
insert into area values('武汉市',1,3)
insert into area values('汉口区',0,8)
insert into area values('随州市',1,3)
go
select * from area
drop table area
/*
id Name order_by father_ID
----------- ---------- ----------- -----------
1 广东省 2 0
2 四川省 2 0
3 湖北省 2 0
4 东莞市 1 1
5 广州市 1 1
6 天河区 0 5
7 绵阳市 1 2
8 武汉市 1 3
9 汉口区 0 8
10 随州市 1 3
(所影响的行数为 10 行)
要求显示为:
name
--------------
广东省
东莞市
广州市
天河区
四川省
绵阳市
湖北省
武汉市
汉口区
随州市
(所影响的行数为 10 行)
*/
--创建原始表
create table Area (id int identity,Name varchar(10) ,order_by int ,father_ID int )
insert into area values('广东省',2,0)
insert into area values('四川省',2,0)
insert into area values('湖北省',2,0)
insert into area values('东莞市',1,1)
insert into area values('广州市',1,1)
insert into area values('天河区',0,5)
insert into area values('绵阳市',1,2)
insert into area values('武汉市',1,3)
insert into area values('汉口区',0,8)
insert into area values('随州市',1,3)
--创建临时表
create table tmp (id int identity,Name varchar(10) ,order_by int ,father_ID int )
go
--创建查询指定节点及其所有子节点的函数
create function f_cid(@ID int) returns @t_level table(id int , level int)
as
begin
declare @level int
set @level = 1
insert into @t_level select @id , @level
while @@ROWCOUNT > 0
begin
set @level = @level + 1
insert into @t_level select a.id , @level
from area a , @t_Level b
where a.father_ID = b.id and b.level = @level - 1
end
return
end
go
--创建存储过程并将数据插入临时表
create proc my_proc
as
begin
declare @id as int
set @id = 0
while exists(select 1 from area where order_by = 2 and id > @id)
begin
set @id = (select min(id) from area where order_by = 2 and id > @id)
insert into tmp(Name ,order_by ,father_ID) select a.name,a.order_by ,a.father_id from area a , f_cid(@id) b where a.id = b.id order by a.id
end
end
go
exec my_proc
--从临时表提取数据并显示
select case when order_by = 2 then name
when order_by = 1 then ' ' + name
when order_by = 0 then ' ' + name
end name
from tmp order by id
drop function f_cid
drop proc my_proc
drop table area , tmp
/*
name
--------------
广东省
东莞市
广州市
天河区
四川省
绵阳市
湖北省
武汉市
汉口区
随州市
(所影响的行数为 10 行)
*/
#6
谢谢各位了,哎..代码编译通过,就是生成不了数据,郁闷啊...CSDN.C#论坛没几个高手解答
#7
#8
帮顶
#9
BOM展现为什么使用Gridview,而不使用树形结构。比如说树形菜单。
#10
展阶后要有相关的BOM信息哈,要求显示的信息不同
#11
C#树形结构?
#12
感觉做法没有问题啊,应该是根节点
或者父子节点设定的问题,递归的时候这个挺难调试的
你先不要忙着绑定treeview那边,先递归显示到一个textbox里整理好递归那个函数再绑定treeview了
其实用devexpress有专门的控件
或者父子节点设定的问题,递归的时候这个挺难调试的
你先不要忙着绑定treeview那边,先递归显示到一个textbox里整理好递归那个函数再绑定treeview了
其实用devexpress有专门的控件
#13
是的。C#树型结构.代码没有任何问题,就是ICBOMGROUP这张表里数据量庞大,调试的时候需要非常长的时间,,寻求简便方法
#14
给个TREEVIEW的例子吧
#15
上面就是在FORM窗体中添加TREEVIEW啊..自动递归添加树节点和根节点的.只是没做到单击一个结点,只是调用这个结点的下一个子结点,而是将所有结点都计算了一次,所以导致数据量庞大...寻求简便方法....
#16
c#不懂,只能帮顶了!
#17
C#,你进的版块不对,这边只针对数据库.
#18
等了几天还是没高手来解答
#19
treeview递归网上有很多C#的代码例
点到treeview结点显示BOM当前层次只用一个datagridview吗?
父件是单一记录,对应子件可能是多条记录,主从表结构
用两个datagridview 或者 多个LABEL 和 一个datagridview吧。
点到treeview结点显示BOM当前层次只用一个datagridview吗?
父件是单一记录,对应子件可能是多条记录,主从表结构
用两个datagridview 或者 多个LABEL 和 一个datagridview吧。
#20
在buildtree过程中,只查询FParentID=0的记录。
加载了所有根结点后,在点击树结点时,查询相应的子结点,并加入树中。
代码不一定准确,但基本上这个思路。LZ可以在此基础上优化一下,如:把数据访问的代码和加载树结点的方法形成函数,可以实现强制刷新的功能,这在当树结点会不时发生变化的情况下也可以应用。
个人以为这种方法,速度快些,每次加载少量的数据,用户不操作的部分不会去查询这部分的,减少了数据网络传输量。速度也是可以保证的。
=====================================================================
如果不一定要一次性的加载所有数据,建议不要用递归了,查询改成按编码和父编码排序吧,写代码当父结点发生变化时,建立相应的结点。
SQL语句:
要保证第一条记录是根结点,如果父结点发生变化,将结点加到相应的位置,有用到结点的查找,如果父结点编号为0,则为树的根结点,否则,要在树的当前结点中查找。
也可以不用SQL的排序,而用DataTable的排序功能来实现这些。
或者,有将递归改成非递归的方法,直接将LZ的方法改成非递归的方法,数据结构教材上有,LZ去看一下。
另外,数据源属性 的get方法,应该在私有变量为空的时候,才去查询数据库吧,而不是取一次值,查一镒数据库,和我的动态加载树结点的情况有些类似。
public void BuildTree(TreeNodeCollection fNodes, Int32 fParentId)
{
SqlConnection thisconnection = new SqlConnection("server=(local);database=GADMEIERP;Integrated Security=true;");
SqlCommand cmd = thisconnection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select FInterID,FParentID,FName,FNumber from ICBOMGROUP where
FParentID=0 ";
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
DataSet ds = new DataSet();
adapter.Fill(ds, "ICBOMGROUP");
this.fSampleDataSource = ds.Tables[0];
//以下填充树
foreach (DataRow row
in this.SampleDataSource.Select(String.Format("FParentID = {0}", fParentId)))
{
TreeNode node = new TreeNode();
node.Text = row["FName"].ToString();
node.Tag = row["FInterID"].ToString();
tv.Nodes.Add(node);
}
}
加载了所有根结点后,在点击树结点时,查询相应的子结点,并加入树中。
private void tv_AfterSelect(object sender, TreeViewEventArgs e)
{
if e.node.nodes.count>0 then //如果有子结点,则不需要查询其子结点
return;
string InterID= (string)e.Node.Tag;
SqlConnection thisconnection = new SqlConnection("server=(local);database=GADMEIERP;Integrated Security=true;");
SqlCommand cmd = thisconnection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select FInterID,FParentID,FName,FNumber from ICBOMGROUP where
FParentID='"+InterID+"'";
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
DataSet ds = new DataSet();
adapter.Fill(ds, "ICBOMGROUP");
this.fSampleDataSource = ds.Tables[0];
//以下填充树
foreach (DataRow row
in this.SampleDataSource.Select(String.Format("FParentID = {0}", fParentId)))
{
TreeNode node = new TreeNode();
node.Text = row["FName"].ToString();
node.Tag = row["FInterID"].ToString();
//应该是类似的方法,因为手头没有现成的例子,LZ凑合着看吧。
e.Node.AddChildNode(node);
//或e.Node.Nodes.add(node);
}
}
代码不一定准确,但基本上这个思路。LZ可以在此基础上优化一下,如:把数据访问的代码和加载树结点的方法形成函数,可以实现强制刷新的功能,这在当树结点会不时发生变化的情况下也可以应用。
个人以为这种方法,速度快些,每次加载少量的数据,用户不操作的部分不会去查询这部分的,减少了数据网络传输量。速度也是可以保证的。
=====================================================================
如果不一定要一次性的加载所有数据,建议不要用递归了,查询改成按编码和父编码排序吧,写代码当父结点发生变化时,建立相应的结点。
SQL语句:
select FInterID,FParentID,FName,FNumber from ICBOMGROUP order by FParentID,FInterID
要保证第一条记录是根结点,如果父结点发生变化,将结点加到相应的位置,有用到结点的查找,如果父结点编号为0,则为树的根结点,否则,要在树的当前结点中查找。
也可以不用SQL的排序,而用DataTable的排序功能来实现这些。
或者,有将递归改成非递归的方法,直接将LZ的方法改成非递归的方法,数据结构教材上有,LZ去看一下。
另外,数据源属性 的get方法,应该在私有变量为空的时候,才去查询数据库吧,而不是取一次值,查一镒数据库,和我的动态加载树结点的情况有些类似。
#21
#1
题目:树型BOM结构递归问题
问题:连接datagridview控件的语句?
问题:连接datagridview控件的语句?
#2
先只求根结点,加到树上,然后在单击的时候,展开下层,这样能提高效率,防止一次性加载时间过长,另外代码也好写。在点击树结点时,根据树结点属性,如ID得到其所有子结点的数据,并将其加载到表格中。
#3
先获取FParentID(父BOM内码) = 0的做为根节点.
然后使用循环逐一获取某根节点的各级节点.
C#不会,帮顶.
然后使用循环逐一获取某根节点的各级节点.
C#不会,帮顶.
#4
http://blog.csdn.net/fredrickhu/archive/2009/09/20/4573387.aspx
http://blog.csdn.net/fredrickhu/archive/2009/09/20/4573382.aspx
只能让你参考下了
http://blog.csdn.net/fredrickhu/archive/2009/09/20/4573382.aspx
只能让你参考下了
#5
如果是SQL,参考如下:
/*
标题:查询所有*节点及其子节点的例
地址:http://topic.csdn.net/u/20090323/21/63a91f51-c4df-464d-ba18-64343deb4e3a.html
作者:爱新觉罗·毓华(十八年风雨,守得冰山雪莲花开)
时间:2009-03-23
地点:广东深圳
*/
[code=SQL]create table Area (id int identity,Name varchar(10) ,order_by int ,father_ID int )
insert into area values('广东省',2,0)
insert into area values('四川省',2,0)
insert into area values('湖北省',2,0)
insert into area values('东莞市',1,1)
insert into area values('广州市',1,1)
insert into area values('天河区',0,5)
insert into area values('绵阳市',1,2)
insert into area values('武汉市',1,3)
insert into area values('汉口区',0,8)
insert into area values('随州市',1,3)
go
select * from area
drop table area
/*
id Name order_by father_ID
----------- ---------- ----------- -----------
1 广东省 2 0
2 四川省 2 0
3 湖北省 2 0
4 东莞市 1 1
5 广州市 1 1
6 天河区 0 5
7 绵阳市 1 2
8 武汉市 1 3
9 汉口区 0 8
10 随州市 1 3
(所影响的行数为 10 行)
要求显示为:
name
--------------
广东省
东莞市
广州市
天河区
四川省
绵阳市
湖北省
武汉市
汉口区
随州市
(所影响的行数为 10 行)
*/
--创建原始表
create table Area (id int identity,Name varchar(10) ,order_by int ,father_ID int )
insert into area values('广东省',2,0)
insert into area values('四川省',2,0)
insert into area values('湖北省',2,0)
insert into area values('东莞市',1,1)
insert into area values('广州市',1,1)
insert into area values('天河区',0,5)
insert into area values('绵阳市',1,2)
insert into area values('武汉市',1,3)
insert into area values('汉口区',0,8)
insert into area values('随州市',1,3)
--创建临时表
create table tmp (id int identity,Name varchar(10) ,order_by int ,father_ID int )
go
--创建查询指定节点及其所有子节点的函数
create function f_cid(@ID int) returns @t_level table(id int , level int)
as
begin
declare @level int
set @level = 1
insert into @t_level select @id , @level
while @@ROWCOUNT > 0
begin
set @level = @level + 1
insert into @t_level select a.id , @level
from area a , @t_Level b
where a.father_ID = b.id and b.level = @level - 1
end
return
end
go
--创建存储过程并将数据插入临时表
create proc my_proc
as
begin
declare @id as int
set @id = 0
while exists(select 1 from area where order_by = 2 and id > @id)
begin
set @id = (select min(id) from area where order_by = 2 and id > @id)
insert into tmp(Name ,order_by ,father_ID) select a.name,a.order_by ,a.father_id from area a , f_cid(@id) b where a.id = b.id order by a.id
end
end
go
exec my_proc
--从临时表提取数据并显示
select case when order_by = 2 then name
when order_by = 1 then ' ' + name
when order_by = 0 then ' ' + name
end name
from tmp order by id
drop function f_cid
drop proc my_proc
drop table area , tmp
/*
name
--------------
广东省
东莞市
广州市
天河区
四川省
绵阳市
湖北省
武汉市
汉口区
随州市
(所影响的行数为 10 行)
*/
#6
谢谢各位了,哎..代码编译通过,就是生成不了数据,郁闷啊...CSDN.C#论坛没几个高手解答
#7
#8
帮顶
#9
BOM展现为什么使用Gridview,而不使用树形结构。比如说树形菜单。
#10
展阶后要有相关的BOM信息哈,要求显示的信息不同
#11
C#树形结构?
#12
感觉做法没有问题啊,应该是根节点
或者父子节点设定的问题,递归的时候这个挺难调试的
你先不要忙着绑定treeview那边,先递归显示到一个textbox里整理好递归那个函数再绑定treeview了
其实用devexpress有专门的控件
或者父子节点设定的问题,递归的时候这个挺难调试的
你先不要忙着绑定treeview那边,先递归显示到一个textbox里整理好递归那个函数再绑定treeview了
其实用devexpress有专门的控件
#13
是的。C#树型结构.代码没有任何问题,就是ICBOMGROUP这张表里数据量庞大,调试的时候需要非常长的时间,,寻求简便方法
#14
给个TREEVIEW的例子吧
#15
上面就是在FORM窗体中添加TREEVIEW啊..自动递归添加树节点和根节点的.只是没做到单击一个结点,只是调用这个结点的下一个子结点,而是将所有结点都计算了一次,所以导致数据量庞大...寻求简便方法....
#16
c#不懂,只能帮顶了!
#17
C#,你进的版块不对,这边只针对数据库.
#18
等了几天还是没高手来解答
#19
treeview递归网上有很多C#的代码例
点到treeview结点显示BOM当前层次只用一个datagridview吗?
父件是单一记录,对应子件可能是多条记录,主从表结构
用两个datagridview 或者 多个LABEL 和 一个datagridview吧。
点到treeview结点显示BOM当前层次只用一个datagridview吗?
父件是单一记录,对应子件可能是多条记录,主从表结构
用两个datagridview 或者 多个LABEL 和 一个datagridview吧。
#20
在buildtree过程中,只查询FParentID=0的记录。
加载了所有根结点后,在点击树结点时,查询相应的子结点,并加入树中。
代码不一定准确,但基本上这个思路。LZ可以在此基础上优化一下,如:把数据访问的代码和加载树结点的方法形成函数,可以实现强制刷新的功能,这在当树结点会不时发生变化的情况下也可以应用。
个人以为这种方法,速度快些,每次加载少量的数据,用户不操作的部分不会去查询这部分的,减少了数据网络传输量。速度也是可以保证的。
=====================================================================
如果不一定要一次性的加载所有数据,建议不要用递归了,查询改成按编码和父编码排序吧,写代码当父结点发生变化时,建立相应的结点。
SQL语句:
要保证第一条记录是根结点,如果父结点发生变化,将结点加到相应的位置,有用到结点的查找,如果父结点编号为0,则为树的根结点,否则,要在树的当前结点中查找。
也可以不用SQL的排序,而用DataTable的排序功能来实现这些。
或者,有将递归改成非递归的方法,直接将LZ的方法改成非递归的方法,数据结构教材上有,LZ去看一下。
另外,数据源属性 的get方法,应该在私有变量为空的时候,才去查询数据库吧,而不是取一次值,查一镒数据库,和我的动态加载树结点的情况有些类似。
public void BuildTree(TreeNodeCollection fNodes, Int32 fParentId)
{
SqlConnection thisconnection = new SqlConnection("server=(local);database=GADMEIERP;Integrated Security=true;");
SqlCommand cmd = thisconnection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select FInterID,FParentID,FName,FNumber from ICBOMGROUP where
FParentID=0 ";
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
DataSet ds = new DataSet();
adapter.Fill(ds, "ICBOMGROUP");
this.fSampleDataSource = ds.Tables[0];
//以下填充树
foreach (DataRow row
in this.SampleDataSource.Select(String.Format("FParentID = {0}", fParentId)))
{
TreeNode node = new TreeNode();
node.Text = row["FName"].ToString();
node.Tag = row["FInterID"].ToString();
tv.Nodes.Add(node);
}
}
加载了所有根结点后,在点击树结点时,查询相应的子结点,并加入树中。
private void tv_AfterSelect(object sender, TreeViewEventArgs e)
{
if e.node.nodes.count>0 then //如果有子结点,则不需要查询其子结点
return;
string InterID= (string)e.Node.Tag;
SqlConnection thisconnection = new SqlConnection("server=(local);database=GADMEIERP;Integrated Security=true;");
SqlCommand cmd = thisconnection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select FInterID,FParentID,FName,FNumber from ICBOMGROUP where
FParentID='"+InterID+"'";
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd;
DataSet ds = new DataSet();
adapter.Fill(ds, "ICBOMGROUP");
this.fSampleDataSource = ds.Tables[0];
//以下填充树
foreach (DataRow row
in this.SampleDataSource.Select(String.Format("FParentID = {0}", fParentId)))
{
TreeNode node = new TreeNode();
node.Text = row["FName"].ToString();
node.Tag = row["FInterID"].ToString();
//应该是类似的方法,因为手头没有现成的例子,LZ凑合着看吧。
e.Node.AddChildNode(node);
//或e.Node.Nodes.add(node);
}
}
代码不一定准确,但基本上这个思路。LZ可以在此基础上优化一下,如:把数据访问的代码和加载树结点的方法形成函数,可以实现强制刷新的功能,这在当树结点会不时发生变化的情况下也可以应用。
个人以为这种方法,速度快些,每次加载少量的数据,用户不操作的部分不会去查询这部分的,减少了数据网络传输量。速度也是可以保证的。
=====================================================================
如果不一定要一次性的加载所有数据,建议不要用递归了,查询改成按编码和父编码排序吧,写代码当父结点发生变化时,建立相应的结点。
SQL语句:
select FInterID,FParentID,FName,FNumber from ICBOMGROUP order by FParentID,FInterID
要保证第一条记录是根结点,如果父结点发生变化,将结点加到相应的位置,有用到结点的查找,如果父结点编号为0,则为树的根结点,否则,要在树的当前结点中查找。
也可以不用SQL的排序,而用DataTable的排序功能来实现这些。
或者,有将递归改成非递归的方法,直接将LZ的方法改成非递归的方法,数据结构教材上有,LZ去看一下。
另外,数据源属性 的get方法,应该在私有变量为空的时候,才去查询数据库吧,而不是取一次值,查一镒数据库,和我的动态加载树结点的情况有些类似。