加入收藏 | 设为首页 | 会员中心 | 我要投稿 晋中站长网 (https://www.0354zz.com/)- 科技、容器安全、数据加密、云日志、云数据迁移!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

C#递归方法成功实现无限级分类显示效果

发布时间:2023-06-05 15:30:15 所属栏目:语言 来源:转载
导读:   这篇文章主要讲述C#递归方法实现无限级分类显示效果,结合完整实例形式分析了C#递归算法与数据元素遍历的相关技巧,具有一定参考借鉴价值,需要的朋友不妨看看。



  数据库表:
  这篇文章主要讲述C#递归方法实现无限级分类显示效果,结合完整实例形式分析了C#递归算法与数据元素遍历的相关技巧,具有一定参考借鉴价值,需要的朋友不妨看看。
 
  数据库表:CategoryInfo
 
  字段名 类型
 
  ciID int //记录序号,自增量
 
  ciName nvarchar(20) //分类名
 
  ciParent int //父分类序号
 
  ciLayer int //所处的层次
 
  ciDescription nvarchar(200) //对分类的描述
 
  分类的类设计
 
  public class CategoryInfo
 
  {
 
  private int ciID;//分类ID
 
  private string ciName;//分类名
 
  private int ciParent;//分类的父分类ID
 
  private string ciDescription;//分类描述
 
  private int ciLayer;//分类所属层次
 
  //构造函数
 
  public CategoryInfo() { }
 
  public CategoryInfo(int cID, string cName, int cParent, string cDescription, int cLayer)
 
  {
 
  this.ciID = cID;
 
  this.ciName = cName;
 
  this.ciParent = cParent;
 
  this.ciDescription = cDescription;
 
  this.ciLayer = cLayer;
 
  }
 
  //属性
 
  public int CategoryID
 
  {
 
  get{ return ciID;}
 
  set { ciID = value;}
 
  }
 
  public string CategoryName
 
  {
 
  get{ return ciName;}
 
  set { ciName = value; }
 
  }
 
  public int CategoryParent
 
  {
 
  get{ return ciParent;}
 
  set { ciParent = value; }
 
  }
 
  public string CategoryDescription
 
  {
 
  get { return ciDescription; }
 
  set { ciDescription = value; }
 
  }
 
  public int CategoryLayer
 
  {
 
  get { return ciLayer; }
 
  set { ciLayer = value; }
 
  }
 
  }
 
  获取子分类的存储过程
 
  CREATE PROCEDURE [dbo].[category_getChild]
 
  @cName nvarchar(20)
 
  AS
 
  BEGIN
 
  DECLARE @tmpID int
 
  SELECT @tmpID=ciID FROM CategoryInfo
 
  WHERE RTRIM(ciName) = RTRIM(@cName)
 
  if(@tmpID IS NOT NULL)
 
  SELECT * FROM CategoryInfo
 
  WHERE ciParent = @tmpID
 
  ORDER BY ciLayer
 
  END
 
  获取子分类的函数
 
  public IList GetChildCategories(IList cInfos,string cName)
 
  {
 
  SqlConnection con = new SqlConnection(connectionString);
 
  SqlCommand cmd = new SqlCommand("category_getChild", con);
 
  cmd.CommandType = CommandType.StoredProcedure;
 
  cmd.Parameters.Add(new SqlParameter(PARAM_CNAME, SqlDbType.NVarChar, 20));
 
  cmd.Parameters[PARAM_CNAME].Value = cName;
 
  IList tmpNames = new List(); //临时存储获取的子
 
  try
 
  {
 
  con.Open();
 
  SqlDataReader reader = cmd.ExecuteReader();
 
  if (reader.HasRows)
 
  {
 
  while (reader.Read())
 
  {
 
  CategoryInfo cInfo = new CategoryInfo(
 
  (int)reader["ciID"],
 
  reader["ciName"].ToString(),
 
  (int)reader["ciParent"],
 
  reader["ciDescription"].ToString(),
 
  (int)reader["ciLayer"]
 
  );
 
  string tmpName = reader["ciName"].ToString();
 
  cInfos.Add(cInfo);//添加获取到的分类到cInfos
 
  tmpNames.Add(tmpName);//添加获取到的子分类名到tmpNames
 
  }
 
  }
 
  }
 
  catch
 
  {
 
  throw new ApplicationException("获取分类出错!");
 
  }
 
  finally
 
  {
 
  con.Close();
 
  }
 
  foreach(string c in tmpNames)
 
  {
 
  cInfos = GetChildCategories(cInfos,c); //递归运算。继续获取子分类
 
  }
 
  return cInfos;
 
  }
 
  说明:在该函数中,tmpNames如果换成是IList,即它添加的元素与cInfos是一样的时,如果要移除其中的一项,则cInfos中会同时移除一项。因为CategoryInfo是类,是引用类型的,而非值类型。所以tmpNames采用了string类型,以避免这个问题。
 
  对上面这个函数直接调用还稍嫌麻烦,上层程序还需要建立一个IList对象,因此可以增加一个函数来调用上面的函数。这样,上层程序只需要提供分类名,以及是否包含本级分类两个参数就可以了。
 
  //获取子分类,其中布尔参数表示是否包含本级分类
 
  public IList GetCategories( string cName, bool IsIncludeSelf)
 
  {
 
  IList cInfos = new List();
 
  cInfos = GetChildCategories(cInfos, cName);
 
  if (IsIncludeSelf == true)
 
  {
 
  cInfos.Insert(0, GetByName(cName));//根据名字获取分类,这个很简单,本文略。
 
  }
 
  return cInfos;
 
  }
 
  注意:采用这种方式时,WEB服务器获取子分类时要在数据库服务器之间有多次往返,降低了性能。采用存储过程实现递归逻辑,直接返回子分类列表的方式应该有更好的性能,尤其是Web服务器与数据库服务器不位于同一台服务器上时,更会受网络影响。
 

(编辑:晋中站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章