当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > C# 无限级分类的实现

ASP.NET
二级域名Cookie问题的解决方法
如何为asp.net网站项目添加子项目
asp.net用url重写URLReWriter实现任意二级域名
asp.net 序列化and反序列化演示
asp.net Timer的使用方法
AjaxControlToolKit DropDownExtender(下拉扩展控件)使用方法
AjaxControlToolKit CalendarExtender(日历扩展控件)的使用方法
让GridView只显示特定用户的数据的方法
让GridView只更新某些特定的数据的方法
ajaxControlToolkit中CascadingDropDown的用法说明
axp.net ScriptManager的简单用法
把程序集安装到全局程序集缓存中的步骤
引用全局程序集缓存内的程序集的方法
asp.net COOKIES需要注意的一点
asp.net UrlReWriter使用经验小结
页面导出为Excel的时间格式的问题
asp.net cookie清除的代码
Asp.net XMLHTTP封装类(GET,Post发送和接收数据)
ASP.NET XmlHttp跨域访问实现代码
Asp.NET 随机码生成基类(随机字母,随机数字,随机字母+数字)

ASP.NET 中的 C# 无限级分类的实现


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-13   浏览: 245 ::
收藏到网摘: n/a

采用存储过程实现递归逻辑,直接返回子分类列表的方式应该有更好的性能,尤其是Web服务器与数据库服务器不位于同一台服务器上时,更会受网络影响。 数据库表: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服务器与数据库服务器不位于同一台服务器上时,更会受网络影响。