C# 无限级分类的实现
C# 无限级分类的实现
发布时间:2016-12-29 来源:查字典编辑
摘要:数据库表:CategoryInfo字段名类型ciIDint//记录序号,自增量ciNamenvarchar(20)//分类名ciParent...

数据库表: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<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"],

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服务器与数据库服务器不位于同一台服务器上时,更会受网络影响。

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新asp.net教程学习
热门asp.net教程学习
编程开发子分类