zoukankan      html  css  js  c++  java
  • B/S项目树状目录结构的完整实现(二)

      上一文中讲了带编号(或说是路径)的树状目录结构基本操作。谢谢有朋友提醒SQL Server2008以上版本可以采用HierarchyId类型字段,也很希望能看到阐述这方面最佳实践的文章。

      理论联系实践,再提高理论认识,这是我一直追求的一个良性循环。本文将目录结构在实践中的一个应用,其实和结构存储方式倒没直接关系。

      先请大家看个截图,这是一个部门选择菜单控件。

    image

      这是一个纯CSS实现的多层级下拉菜单,相对来说在网页上较少见。当点击选择一个部门时,旁边的文本框会显示该部门的各层级名称,并将该部门编号记录到一个隐藏域中,用于提交查询。

      这个控件和遍历目录下的文件一样,用递归方式写入HTML代码,应该算基本的编程技术了。

    public partial class SectionMenu : System.Web.UI.UserControl
    {
        protected StringBuilder HtmlBuilder = new StringBuilder();
    
        protected void Page_Load(object sender, EventArgs e)
        {
            WriteSectionMenu(null);
        }
    
        public void WriteSectionMenu(string parentID)
        {
            var topSections = SectionHelper.GetSubSections(parentID, true); //读取一级子部门
    
            if (topSections.Count < 1) return;
            HtmlBuilder.Append("<ul>");
    
            foreach (var item in topSections)
            {
                HtmlBuilder.AppendFormat("<li><a href=\"{0}\">{1}</a>", item.SectionNo, item.Name);
    
                WriteSectionMenu(item.SectionNo);
                HtmlBuilder.Append("</li>");
            }
    
            HtmlBuilder.Append("</ul>");
        }
    }
    

      菜单前端实现参考示例(单html文件):下载

      这种下拉菜单方便之处一目了然,缺点是导致页面体积显著增大,像示例那种,一两百个部门,只增加了十几KB还好,更多的话就令人难以接受了。解决的方案我认为只有一种—缓存。

      缓存是B/S开发中的最深的一门学问,没有之一。一个男人,如果能在老妈和老婆中间左右逢源,便是一个不算失败的男人;如果男人还能照顾到子女的平衡,必须是一个优秀的男人。同样,在Web开发中,能灵活运用数据缓存和输出缓存的,便是一个不错的程序员;若能考虑充分利用客户端缓存,应该就是个杰出的程序员;而如果他能设计全局缓存和节点缓存的话,我想那是大师级人物吧。

      我想提供一下Server端的数据缓存和输出缓存,以及Client的浏览器缓存方案,可惜我还没实现完整,放在下文再讲吧。有朋友似乎对我上文中的理论不太认可,我提供两段Linq To SQL代码,实现的功能相同,都是查找某部门员工的请假记录(Leave表),但存储结构不同。

      记录父级编号存储方式:

    var sectionNo = "00";   //部门编号
    
    //所有层级子部门键人集合
    var subSections = SectionHelper.GetSubSections(sectionNo, false).Select(s=>s.Id).ToList(); 
    
    var result = from l in db.Leaves
                 join p in db.PersonInfoes on l.Alias equals p.Alias
                 where subSections.Contains(p.SectionId)
                 select l;
                 
    query = (result as ObjectQuery).ToTraceString();
    

      生成的SQL语句:

    SELECT [Extent1].[ID] AS [ID], [Extent1].[Type] AS [Type], [Extent1].[BeginTime] AS [BeginTime], [Extent1].[EndTime] AS [EndTime], [Extent1].[Alias] AS [Alias], [Extent1].[AssistantID] AS [AssistantID], [Extent1].[PostTime] AS [PostTime] FROM [Affair].[Leave] AS [Extent1] INNER JOIN [Firm].[PersonInfo] AS [Extent2] ON [Extent1].[Alias] = [Extent2].[Alias] WHERE [Extent2].[SectionId] IN (1,2,5,7,13,24,……,N)

      记录路径编号存储方式:

    var sectionNo = "00";   //部门编号
    var result = from l in db.Leaves
                 join p in db.PersonInfoes on l.Alias equals p.Alias
                 where p.SectionNo.IndexOf(sectionNo) == 0
                 select l;
    
    Console.WriteLine((result as ObjectQuery).ToTraceString()); 
    

      生成的SQL语句是:

    SELECT [Extent1].[ID] AS [ID], [Extent1].[Type] AS [Type], [Extent1].[BeginTime] AS [BeginTime], [Extent1].[EndTime] AS [EndTime], [Extent1].[Alias] AS [Alias], [Extent1].[AssistantID] AS [AssistantID], [Extent1].[PostTime] AS [PostTime] FROM [Affair].[Leave] AS [Extent1] INNER JOIN [Firm].[PersonInfo] AS [Extent2] ON [Extent1].[Alias] = [Extent2].[Alias] WHERE 0 = (( CAST(CHARINDEX(@p__linq__0, [Extent2].[SectionNo]) AS int)) - 1)

      孰优孰劣,大家可以比较下生成的SQL语句,应该会有一些概念。

  • 相关阅读:
    img标签为什么可以设置宽高
    高度和宽度的操作
    自增自减运算符
    读取标签内容:innerHTML和innerText的区别 text()和html()的区别
    js中的常用方法
    js中style,currentStyle和getComputedStyle的区别以及获取css操作方法(考虑兼容性和局限性)
    IE盒模型与W3C盒模型区别
    css四种定位方式及其区别
    css隐藏元素的方法何区别
    Hibernate之HQL
  • 原文地址:https://www.cnblogs.com/XmNotes/p/2015980.html
Copyright © 2011-2022 走看看