首页 > 开发 > 综合 > 正文

用C#获取无限多级分类的实现

2024-07-21 02:25:44
字体:
来源:转载
供稿:网友

所做的小项目中需要多级分类, 试着学习实现多级分类。由于对存储过程本身并不大熟悉,也不想借助于treeview,于是递归逻辑采用c#实现,配合数数据库完成了多级分类的获取方法。增加分类节点应该说是比较简单的,此文暂略。

数据库表:categoryinfo

字段名           类型

ciid                  int                        //记录序号,自增量

ciname         nvarchar(20)       //分类名

ciparent           int                       //父分类序号

cilayer              int                      //所处的层次

cidescription     nvarchar(200)   //对分类的描述

获取子分类的存储过程

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<categoryinfo> getchildcategories(ilist<categoryinfo> 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<string> tmpnames = new list<string>();   //临时存储获取的子
            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"],
                            (int)reader["cinum"],
                            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<categoryinfo>,即它添加的元素与cinfos是一样的时,如果要移除其中的一项,则cinfos中会同时移除一项。因为categoryinfo是类,是引用类型的,而非值类型。所以tmpnames采用了string类型,以避免这个问题。

对上面这个函数直接调用还稍嫌麻烦,上层程序还需要建立一个ilist<categoryinfo>对象,因此可以增加一个函数来调用上面的函数。这样,上层程序只需要提供分类名,以及是否包含本级分类两个参数就可以了。

        //获取子分类,其中布尔参数表示是否包含本级分类
        public ilist<categoryinfo> getcategories( string cname, bool isincludeself)
        {
            ilist<categoryinfo> cinfos = new list<categoryinfo>();
            cinfos = getchildcategories(cinfos, cname);
            if (isincludeself == true)
            {               
                cinfos.insert(0, getbyname(cname));//根据名字获取分类,这个很简单,本文略。
            }
            return cinfos;
        }
           

注意:采用这种方式时,web服务器获取子分类时要在数据库服务器之间有多次往返,降低了性能。采用存储过程实现递归逻辑,直接返回子分类列表的方式应该有更好的性能,尤其是web服务器与数据库服务器不位于同一台服务器上时,更会受网络影响。

 

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表