递归调用是程序设计中一个非常重要的方法。此法简单直观,结构清晰,程序易读,给我们编制程序和调试程序带来很大的方面,但计算机的执行过程比较复杂,时空性能相对较差。这里从一个分类查询开始说起。要求根据一张产品表,里面有产品的信息,还有产品编码,产品的父级编码,产品是否选中(逻辑删除)。这里是通过一个TreeView来实现的,选择父节点就会选中相应的子节点,然后点击确定,就表示添加此产品;如果只选择子节点,那父节点不会自动选中,也可以添加产品信息。这里要实现的分类查询就是,只要选中子节点,那么查找后,不管有没有选中父节点,父节点都会相应的出现,并加以颜色区分。
由上图可以看出,不管煤油有没有选中,在分类查询里如果其子节点被选中了,它就会显示出来。
实现过程如下:
首先,通过查找先找出所有相应的选中产品来,并放到DataTable中。
string strSql = "select 产品编码,产品父级编码,其他信息 from 产品表 where 标识选中 = 1";
DataTable dt = GetDataTable(strSql);
然后调用递归方法,找到子节点所有的父节点;大致程序如下:
foreach(DataRow dr in dt.Rows)
{
strBm += getSupId(dr["bm"].ToString()) + ",";
}
/// <summary>
/// 获得父级编码
/// </summary>
/// <param name="strSubId">子节点编码</param>
private string getSupId(string strSubId)
{
string strSql = "select 产品父级编码 from 产品表 where 产品编码 = " + strSubId+ "";
DataTable dt = GetDataTable(strSql);
//如果父级节点为空,它就是父级节点,返回它的编码;否则的话,传入它的编码作为父级节点继续查找
if (dt.Rows[0][0].ToString() == "")
{
return strSubId;
}
else
{
//递归调用
return getSupId(dt.Rows[0][0].ToString());
}
}
其次,当找到所有的父节点后,再进行查找,找相应的子节点,因为在分类查询中只有二级结构,即不管树结构中分的几级,而在分类查找中只要求两级。
strSql = "select 产品编码,产品父级编码,其他信息 from 产品表 where 产品编码 in(" + strBM + ")";
DataTable dt = GetDataTable(strSql);
DataTable dtNew = null;
foreach(DataRow dr in dt.Rows)
{
dtNew.Rows.Add(dr.ItemArray);
//获得子集编码
getSubId(dr[产品编码].ToString(),ref strSubId);
//
strSql = "select 产品编码,产品父级编码,其他信息 from 产品表 where 标识选中 = 1 and 产品编码 in(" + strSubId+ ")";
//添加新DataTable中,此DataTable即为最中所要实现的DataTable
dtNew.GetDataTable(strSql);
}
/// <summary>
/// 获得子级编码
/// </summary>
/// <param name="strSupId">父节点</param>
/// <param name="strSubId">子节点</param>
private void getSubId(string strSupId,ref string strSubId)
{
string strSql = "select 产品编码 from 产品表 where 产品父级编码 = " + strSupId + "";
DataTable dt = GetDataTable(strSql);
foreach(DataRow dr in dt.Rows)
{
if(dr[0].ToString() != "")
{
strSubId += dr[0].ToString() + ",";
//递归调用
getSubId(dr[0].ToString(),ref strSubId);
}
}
}
至此差不多实现了所需要的功能。但是执行速度确实慢了下来。除了使用递归算法使速度降下来的原因外,还有对父节点查找子节点getSubId方法的过程中,没有过滤掉没有标识的产品,而是在新添加到DataTable的过程中过滤掉的,这样的话,可能一个产品会有很多个子节点,从而使速度降了下来。如果将过滤的地方改到getSubId方法中,速度是不是就会提高很多呢?但是这样的话,我们所要求的功能是不是还能完好的实现呢?答案就是速度会提高,功能会打折扣。