C#怎样才能提高读取SQL数据库的速度? 我现在做的窗口用第三方控件AdvTree(树形节点)和数据库中的院系名,专业名和班级名进行绑定,其中院系名为一级节点,专业名为二级节点,班级名为三级节点.,院系名,专业名和班级名这几个加起来的数据有1670条的,调试的时候这个窗口弹出来要10秒左右,总是觉得很慢,该怎么办? (老师不能让我们用数据集,要全用代码实现) 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 我一般是用这种方法的,请问哪里可以再改进一下?//定义数据行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); } } } } } 我现在知道为什么读取那么慢了,问题都解决了~~因为我在自定义类中调用查询表存储过程后,都把那个通道销毁了,这不知道是不是原因之一;现在我先定义3个行集合分别把自定义类的实例中方法返回的院系,专业,班级三个表的行都装起来,然后foreach中都改用定义的三个集合,这样的话可能访问数据库的次数少了,一下子读取出来了~ 我的建议:1670 条记录一次性读出来,然后再用LINQ组合成TREENODE,这样就只有一次数据库访问了。LINQ在内存对象上查询也很快。 可以用递归的方法 大概的举个例子第一种填充时展开节点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(); } } } 有没有发现使用DotNetBar树形结构的时候,引起内存溢出的现象 AxAcroPDF怎么设置全屏显示 关于Main方法的参数问题? Access数据库无法删除数据 [求助]在其他机器上安装.net2.0做的软件,但不知道对方机器上有没有.net2.0的框架!怎么判断? C#多线程操作内存的问题 winform numericUpDown控件显示问题 ado.ne访问access是不是比访问sqlserver慢。有什么解决方法吗? 请问如何在C#中拷贝控件? winform下国际化支持的奇怪问题。。。 請問哪里有專門的程序員即時聊天室? 請介紹几個. 無盡感激! winfrom中Panel显示问题 能不能获取SQL server企业管理器里生成的脚本
//定义数据行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);
}
} }
} }
LINQ在内存对象上查询也很快。
第一种填充时展开节点
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();
}
}
}