在度娘上查了大半个月的资料,最后发现每个网友分享的文章都有一定的错误(PS:大家是故意的么?)。最后是在看了一个ASP版本后知道了大概流程;看了一个存储过程实现的文章后知道了大概需要的功能;看了一个SQL语句看到了比较直观的实现;看了一个php示例后才知道最复杂的一个功能的实现。每篇文章都是网友们自己正在使用或已经测试通过的,但都很巧,恰好关键地方就有点出错,不过还是感谢这些资料了,不然我也搞不出来。

  因为查了很久的资料,基本上没有可用的,所以一直不敢直接写到项目的DAL里面,就直接在控制器里面写方法进行了调试,暂时没考虑什么意外情况和效率问题,毕竟出现上述问题的前提条件是你这个功能要实现吧,呵呵,下面直接上代码(PS:有点丑,见谅)。

       //数据初始化,反正失败了几十次,所以就在前面写了段初始化的代码,经常用到
cManager.DelByCondition(c => c.Id != );
Models.CmsMiee_Article_Category cate1 = new Models.CmsMiee_Article_Category() { Name = "商品", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
Models.CmsMiee_Article_Category cate2 = new Models.CmsMiee_Article_Category() { Name = "食品", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
Models.CmsMiee_Article_Category cate3 = new Models.CmsMiee_Article_Category() { Name = "肉类", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
Models.CmsMiee_Article_Category cate4 = new Models.CmsMiee_Article_Category() { Name = "猪肉", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
Models.CmsMiee_Article_Category cate5 = new Models.CmsMiee_Article_Category() { Name = "蔬菜类", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
Models.CmsMiee_Article_Category cate6 = new Models.CmsMiee_Article_Category() { Name = "白菜", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
Models.CmsMiee_Article_Category cate7 = new Models.CmsMiee_Article_Category() { Name = "电器", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
Models.CmsMiee_Article_Category cate8 = new Models.CmsMiee_Article_Category() { Name = "电视机", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
Models.CmsMiee_Article_Category cate9 = new Models.CmsMiee_Article_Category() { Name = "电冰箱", ClassLeftNum = , ClassRightNum = , ListSkin = "test", ContentSkin = "text" };
cManager.Add(cate1);
cManager.Add(cate2);
cManager.Add(cate3);
cManager.Add(cate4);
cManager.Add(cate5);
cManager.Add(cate6);
cManager.Add(cate7);
cManager.Add(cate8);
cManager.Add(cate9);
return new MvcHtmlString("OK");        //整体数据,后面涉及一些基本操作所调用的实体有些就是用的这个
long nodeId = ;
Models.CmsMiee_Article_Category cate = cManager.GetById(nodeId);
//一、计算A节点的子节点数。 $num = ($AR - $AL -1)/2;
return Json((cate.ClassRightNum - cate.ClassLeftNum - ) / , JsonRequestBehavior.AllowGet);        //二、查找A节点的所有子节点。
select * from tree where L > $AL and R < $AR order by L asc;
List<Models.CmsMiee_Article_Category> childCate = cManager.GetListByCondition(c => c.ClassLeftNum > cate.ClassLeftNum && c.ClassRightNum < cate.ClassRightNum, c => c.ClassLeftNum);
return Json(childCate, JsonRequestBehavior.AllowGet);        //三、查找A节点的所有父节点。
select * from tree where L < $AL and R > $AR order by L desc;
List<Models.CmsMiee_Article_Category> parentCate = cManager.GetListByCondition(c => c.ClassLeftNum < cate.ClassLeftNum && c.ClassRightNum > cate.ClassRightNum, c => c.Id);
string r1 = "";
foreach (Models.CmsMiee_Article_Category c in parentCate)
{
r1 += "," + c.Name;
}
return new MvcHtmlString(r1);        //四、在A节点下增加子节点B,B作为最后一个子节点。
update tree set L = L + where L >= $AR;
update tree set R = R + where R >= $AR;
insert into tree (name, L, R) values('B', $AR-, $AR);
List<Models.CmsMiee_Article_Category> update1 = cManager.GetListByCondition(c => c.ClassLeftNum >= cate.ClassRightNum, c => c.ClassLeftNum);
List<Models.CmsMiee_Article_Category> update2 = cManager.GetListByCondition(c => c.ClassRightNum >= cate.ClassRightNum, c => c.ClassLeftNum);
foreach (Models.CmsMiee_Article_Category c in update1)
{
c.ClassLeftNum += ;
cManager.Modify(c, "ClassLeftNum");
}
foreach (Models.CmsMiee_Article_Category c in update2)
{
c.ClassRightNum += ;
cManager.Modify(c, "ClassRightNum");
}
Models.CmsMiee_Article_Category newClass = new Models.CmsMiee_Article_Category() { Name = "北极企鹅", ClassLeftNum = cate.ClassRightNum - , ClassRightNum = cate.ClassRightNum - , ListSkin = "test", ContentSkin = "text" };
cManager.Add(newClass);
return Json("OK", JsonRequestBehavior.AllowGet);        //五、输出节点下的所有子节点,并提供层级等信息以便生成节点树
List<Models.CmsMiee_Article_Category> childCate = cManager.GetListByCondition(c => c.ClassLeftNum >= cate.ClassLeftNum && c.ClassRightNum <= cate.ClassRightNum, c => c.ClassRightNum);
List<Models.CmsMiee_Article_Category_Layer> cateList = new List<Models.CmsMiee_Article_Category_Layer>();
foreach (Models.CmsMiee_Article_Category c in childCate)
{
Models.CmsMiee_Article_Category_Layer newCate = new Models.CmsMiee_Article_Category_Layer();
newCate.Id = c.Id;
newCate.Name = c.Name;
newCate.ClassLeftNum = c.ClassLeftNum;
newCate.ClassRightNum = c.ClassRightNum;
newCate.ListSkin = c.ListSkin;
newCate.ContentSkin = c.ContentSkin;
newCate.AddTime = c.AddTime;
newCate.DelTime = c.DelTime;
newCate.IsDeleted = c.IsDeleted;
newCate.Layer = cManager.GetListByCondition(c1 => c1.ClassLeftNum <= newCate.ClassLeftNum && c1.ClassRightNum >= newCate.ClassRightNum, c1 => c.ClassLeftNum).Count;
cateList.Add(newCate);
}
//拼接节点树
string tree = "";
foreach (Models.CmsMiee_Article_Category_Layer cl in cateList)
{
string tab = "";
//根据层级生成制表符
for (int index = ; index < cl.Layer; index++) { tab += " "; }
tree += tab + cl.Name + " - 层级:" + cl.Layer + "\n";
}
MvcHtmlString result = new MvcHtmlString("<pre>" + tree + "</pre>");
return result;        //六、删除A节点。先要计出该节点及其所有子节点所占的左右值空间,将这些节点删掉,然后更新其它节点的左右值。
$num = $AR - $AL + ;
delete from tree where L >= $AL and R <= $AR;
update tree set R = R - $num where R > $AR;
update tree set = L - $num where L > $AR;
long cateLAR = cate.ClassRightNum - cate.ClassLeftNum + ;
cManager.DelByCondition(c => c.ClassLeftNum >= cate.ClassLeftNum && c.ClassRightNum <= cate.ClassRightNum);
List<Models.CmsMiee_Article_Category> update1 = cManager.GetListByCondition(c => c.ClassRightNum > cate.ClassRightNum, c => c.ClassRightNum);
List<Models.CmsMiee_Article_Category> update2 = cManager.GetListByCondition(c => c.ClassLeftNum > cate.ClassRightNum, c => c.ClassRightNum);
foreach (Models.CmsMiee_Article_Category c in update1)
{
c.ClassRightNum -= cateLAR;
cManager.Modify(c, "ClassRightNum");
}
foreach (Models.CmsMiee_Article_Category c in update2)
{
c.ClassLeftNum -= cateLAR;
cManager.Modify(c, "ClassLeftNum");
}
MvcHtmlString result = new MvcHtmlString("OK");
return result;        //七、分类的父级修改
//1.如果目标节点的ClassRightNum小于当前节点的ClassRightNum;并且目标节点的ClassLeftNum大于当前节点的ClassLeftNum,则返回第一个错误:
long selfCategoryId = ; //要移动的节点
long newCategoryId = ; //目标节点
Models.CmsMiee_Article_Category selfCategory = cManager.GetById(selfCategoryId);
Models.CmsMiee_Article_Category newCategory = cManager.GetById(newCategoryId);
if (selfCategory == null) return new MvcHtmlString("当前所操作的分类不存在!");
if (newCategory == null) return new MvcHtmlString("您选择的新分类不存在!");
long selfLeft = selfCategory.ClassLeftNum;
long selfRight = selfCategory.ClassRightNum;
long value = selfRight - selfLeft;
//取得该分类下面的所有分类,包括自身
List<Models.CmsMiee_Article_Category> selfCategories = cManager.GetListByCondition(c => c.ClassLeftNum >= selfLeft && c.ClassRightNum <= selfRight, c => c.Id);
//将所有分类的ID写入数组以便更新左右值
long[] selfCategoryIDS = new long[selfCategories.Count];
for (int index = ; index < selfCategoryIDS.Length; index++)
{
selfCategoryIDS[index] = Convert.ToInt32(selfCategories[index].Id);
}
//将所有子类及自身的id组成字符串,逗号分隔
string inIDS = string.Join(",", selfCategoryIDS);
long parentLeft = newCategory.ClassLeftNum;
long parentRight = newCategory.ClassRightNum;
//读取新父级分类的所有父级分类及其层级
List<Models.CmsMiee_Article_Category> newParentCate1 = cManager.GetListByCondition(c => c.ClassLeftNum < newCategory.ClassLeftNum && c.ClassRightNum > newCategory.ClassRightNum, c => c.Id);
List<Models.CmsMiee_Article_Category_Layer> newParentCate = new List<Models.CmsMiee_Article_Category_Layer>();
foreach (Models.CmsMiee_Article_Category c in newParentCate1)
{
Models.CmsMiee_Article_Category_Layer newCate = new Models.CmsMiee_Article_Category_Layer();
newCate.Id = c.Id;
newCate.Name = c.Name;
newCate.ClassLeftNum = c.ClassLeftNum;
newCate.ClassRightNum = c.ClassRightNum;
newCate.ListSkin = c.ListSkin;
newCate.ContentSkin = c.ContentSkin;
newCate.AddTime = c.AddTime;
newCate.DelTime = c.DelTime;
newCate.IsDeleted = c.IsDeleted;
newCate.Layer = cManager.GetListByCondition(c1 => c1.ClassLeftNum <= newCate.ClassLeftNum && c1.ClassRightNum >= newCate.ClassRightNum, c1 => c.ClassLeftNum).Count;
newParentCate.Add(newCate);
}
//判断是前移还是后移,并更新数据库
if (parentRight > selfRight)
{
//后移
//更新左边值
//update CmsMiee_Article_Category set ClassLeftNum=ClassLeftNum-value-1 where ClassLeftNum>selfRight and ClassRightNum<=parentRight
List<Models.CmsMiee_Article_Category> tempCategories = cManager.GetListByCondition(c => c.ClassLeftNum > selfRight && c.ClassRightNum <= parentRight, c => c.Id);
foreach (Models.CmsMiee_Article_Category c in tempCategories)
{
c.ClassLeftNum = c.ClassLeftNum - value - ;
cManager.Modify(c, "ClassLeftNum");
}
//更新新父类的父类的左边值
foreach (Models.CmsMiee_Article_Category_Layer c in newParentCate)
{
if (c.Layer == ) continue;
c.ClassLeftNum = c.ClassLeftNum - value - ;
//转换为不带层级的分类后更新到数据库中
Models.CmsMiee_Article_Category result = cManager.GetById(c.Id);
result.ClassLeftNum = c.ClassLeftNum;
cManager.Modify(result, "ClassLeftNum");
}
//update CmsMiee_Article_Category set ClassRightNum=ClassRightNum-value-1 where ClassRightNum>selfRight and ClassRightNum<parentRight
//更新右边值
tempCategories = cManager.GetListByCondition(c => c.ClassRightNum > selfRight && c.ClassRightNum < parentRight, c => c.Id);
foreach (Models.CmsMiee_Article_Category c in tempCategories)
{
c.ClassRightNum = c.ClassRightNum - value - ;
cManager.Modify(c, "ClassRightNum");
}
long tempValue = parentRight - selfRight - ;
tempCategories = cManager.GetListByCondition(c => selfCategoryIDS.Contains(c.Id), c => c.Id);
//update CmsMiee_Article_Category set ClassLeftNum=ClassLeftNum+tempValue,ClassRightNum=ClassRightNum+tempValue where Id in(selfCategoryIDS)
foreach (Models.CmsMiee_Article_Category c in tempCategories)
{
c.ClassLeftNum = c.ClassLeftNum + tempValue;
c.ClassRightNum = c.ClassRightNum + tempValue;
cManager.Modify(c, "ClassLeftNum", "ClassRightNum");
}
}
else
{
//前移
List<Models.CmsMiee_Article_Category> tempCategories = cManager.GetListByCondition(c => c.ClassLeftNum > parentRight && c.ClassLeftNum < selfLeft, c => c.Id);
//更新左边值
foreach (Models.CmsMiee_Article_Category c in tempCategories)
{
c.ClassLeftNum = c.ClassLeftNum + value + ;
cManager.Modify(c, "ClassLeftNum");
}
//更新右边值
tempCategories = cManager.GetListByCondition(c => c.ClassRightNum >= parentRight && c.ClassRightNum < selfLeft, c => c.Id);
foreach (Models.CmsMiee_Article_Category c in tempCategories)
{
c.ClassRightNum = c.ClassRightNum + value + ;
cManager.Modify(c, "ClassRightNum");
}
long tempValue = selfLeft - parentRight;
tempCategories = cManager.GetListByCondition(c => selfCategoryIDS.Contains(c.Id), c => c.Id);
foreach (Models.CmsMiee_Article_Category c in tempCategories)
{
c.ClassLeftNum = c.ClassLeftNum - tempValue;
c.ClassRightNum = c.ClassRightNum - tempValue;
cManager.Modify(c, "ClassLeftNum", "ClassRightNum");
}
}
return new MvcHtmlString("操作完成!");

  估计是特别乱了,昨天整理了好久,总算是放到DAL里面去了,最后一个修改的功能,步骤稍微有点繁琐。为以防万一,我用的是事务,反正很简单,SaveChange你懂的》。。。

  变量里面用到的cManager对象是BLL中管理分类用的类,没有什么特别,只是继承了父类的增删改查功能。

  这段代码只是我测试、学习的时候用到的,后来改动了很多地方,不过关于数据库操作和无限级分类这一块,基本上没什么改动了。没这么无私,所以懒得整理了(PS:我要是像大神们那样整理,估计代码中也会“恰巧”出现一点点关键地方的错误了,呵呵)。所以需要用的朋友可以自行整理一下。

左右值无限级分类 MVC + EntityFramework 的简单实现的更多相关文章

  1. (实用篇)PHP递归实现无限级分类

    在一些复杂的系统中,要求对信息栏目进行无限级的分类,以增强系统的灵活性.那么PHP是如何实现无限级分类的呢?我们在本文中使用递归算法并结合mysql数据表实现无限级分类. 在一些复杂的系统中,要求对信 ...

  2. php利用递归函数实现无限级分类

    相信很多学php的很多小伙伴都会尝试做一个网上商城作为提升自己技术的一种途径.各种对商品分类,商品名之类的操作应该是得心应手,那么就可以尝试下无限级分类列表的制作了. 什么是无限级分类? 无限级分类是 ...

  3. PHP无限级分类-递归(不推荐)

    [http://www.helloweba.com/view-blog-204.html] 在一些复杂的系统中,要求对信息栏目进行无限级的分类,以增强系统的灵活性.那么PHP是如何实现无限级分类的呢? ...

  4. PHP递归实现无限级分类

    在一些复杂的系统中,要求对信息栏目进行无限级的分类,以增强系统的灵活性.那么PHP是如何实现无限级分类的呢?我们在本文中使用递归算法并结合mysql数据表实现无限级分类. 在一些复杂的系统中,要求对信 ...

  5. MVC无限级分类01,分层架构,引入缓存,完成领域模型与视图模型的映射

    本系列将使用zTree来创建.编辑关于品牌.车系.车型的无限级分类,使用datagrid显示,源码在github.先上最终效果: datagrid显示所有记录.分页,提供添加.修改.删除按钮,并提供简 ...

  6. MVC无限级分类02,增删改查

    继上一篇"MVC无限级分类01,分层架构,引入缓存,完成领域模型与视图模型的映射",本篇开始MVC无限级分类的增删改查部分,源码在github. 显示和查询 使用datagrid显 ...

  7. 无限级分类Asp.net Mvc实现

    无限级分类Asp.net Mvc实现   无限级分类涉及到异步加载子类.加载当前类和匹配问题,现在做一个通用的实现.   (一) 效果如下:   (二)设计.实现及使用 (1)数据库 (a)表设计db ...

  8. php无限级分类实战——评论及回复功能

    经常在各大论坛或新闻板块详情页面下边看到评论功能,当然不单单是直接发表评论内容那么简单,可以对别人的评论进行回复,别人又可以对你的回复再次评论或回复,如此反复,理论上可以说是没有休止,从技术角度分析很 ...

  9. FreeSql 使用 ToTreeList/AsTreeCte 查询无限级分类表

    关于无限级分类 第一种方案: 使用递归算法,也是使用频率最多的,大部分开源程序也是这么处理,不过一般都只用到四级分类. 这种算法的数据库结构设计最为简单.category表中一个字段id,一个字段fi ...

随机推荐

  1. CentOS6.X 系统安装后的基础优化

    特别说明:克隆之后的网卡修改 1 编辑eth0的配置文件:vi /etc/sysconfig/network-scripts/ifcfg-eth0, 删除HWADDR地址那一行及UUID的行如下: H ...

  2. postgresql 备份与恢复

    备份 C:\PostgreSQL\\bin>pg_dump -h localhost -p -U postgres Mes > d:/.bak 恢复 C:\PostgreSQL\\bin& ...

  3. 文件夹操作之判断是否存在(Directory)

    Directory类用于操作文件夹,用于创建.移动和枚举目录和子目录的静态方法.DirectoryInfo类用于典型操作,如复制,移动,重命名,创建和删除目录.他们都可用于获取和设置相关属性或有关创建 ...

  4. Winform截图小程序

    今天闲时做的一个Demo,做得并不好,只是实现了最基本的截图功能 主要的思路就是 先打开一个主窗体,点击"截图按钮" 会出现一个半透明的小窗体(可以拉伸放大缩小) 然后利用Grap ...

  5. Skype坑爹报错:“旧版本无法删除,请联络您的技术支持小组 ”的解决办法

    真是恶心的让人想吐的报错.现在终于解决了,跟大家分享一下方法. 先给问题截个图,如下 首先当我去搜解决办法之前,我已经在[控制面板]的[卸载程序]里把Skype删除了,真是让我后悔不已的操作啊!!因为 ...

  6. 从MySQL到ORM(三):连接、存储过程和用户权限

    一.联结表 数据仍使用前文中的数据. 1.子查询 作为子查询的SELECT语句只能查询单个列.企图检索多个列将返回错误. -- 作为查询条件使用 -- 查看TNT2订单对应的客户ip(order表) ...

  7. springboot的依赖注入报null的问题

    最近使用springboot开发项目,使用到了依赖注入,频繁的碰到注入的对象报空指针,错误如下 java.lang.NullPointerException: null at com.mayihc.a ...

  8. cf1090 I.Minimal Product(贪心)

    题意 题目链接 给出长度为\(n\)的序列\(a\),序列中的元素取值为\([-2e9, 2e9]\) 找到两个位置\((i, j) (i <j, a[i] < a[j])\),最小化\( ...

  9. css,js移动资源

    随着移动市场的逐步扩大及相关技术的日趋完善,对前端开发提出了新的岗位要求,在继承前人成果的基础上需要在新的历史条件下有新的创新.移动端的开发,虽然没有IE6众多问题的折磨,但是多平台,多设备的兼容,也 ...

  10. gulp & webpack整合

    为什么需要前端工程化? 前端工程化的意义在于让前端这个行业由野蛮时代进化为正规军时代,近年来很多相关的工具和概念诞生.好奇心日报在进行前端工程化的过程中,主要的挑战在于解决如下问题:✦ 如何管理多个项 ...