代码之家  ›  专栏  ›  技术社区  ›  XardasLord

从邻接模型+嵌套集模型(mptt)绘制树层次结构的方法

  •  0
  • XardasLord  · 技术社区  · 6 年前

    我有一个带有sql server db的.net core 2.2应用程序,使用邻接模型+嵌套集模型存储用户的层次结构。我在用英孚核心。我的域名如下:

        public class MatrixPosition
        {
            public Guid Id { get; set; }
            public string Name { get; set; }
            public Guid? ParentId { get; set; }
            public int Left { get; set; }
            public int Right { get; set; }
            public int DepthLevel { get; set; }
    }
    

    最重要的元素当然有 ParentId = null DepthLevel = 0

    我想把这个结构显示为一些树结构图形。有人对此有什么想法或工作实例吗?

    0 回复  |  直到 6 年前
        1
  •  1
  •   dazedandconfused    6 年前

    我过去使用的一种方法是将一些繁重的工作转移到外部框架上,比如 Graphviz . 你可以让你的应用程序生成一个文本文件,由一个名为“dot”的实用程序处理以生成图形。优点是它是开源的、广泛使用的、跨平台的。缺点是,让图表看起来完全符合您的要求的语法可能会令人困惑。下面是我使用您的模式创建的一个示例。

    首先,我创建了一个递归查询来返回记录及其父记录。我用名字填充它,好像它是一个组织结构图。你可以找到小提琴 here 如果你想做实验,这里有个问题…

    WITH cteEEs AS (
      SELECT employees.Id, employees.ParentId, employees.Name, employees.[Left], employees.[Right] FROM employees WHERE employees.ParentId IS NULL
      UNION ALL 
      SELECT employees.Id, employees.ParentId, employees.Name, employees.[Left], employees.[Right] FROM employees JOIN cteEEs ON (employees.ParentId = cteEEs.Id)
    )
    
    SELECT * FROM cteEEs
    

    通过使用以下代码…

    var nodeRelationships = new StringBuilder();
    var nodeDetails = new StringBuilder();
    
    foreach(var node in results)
    {
        if(!string.IsNullOrEmpty(node.ParentId))
        {
            nodeRelationships.AppendLine($"\t\"{node.ParentId}\" -> \"{node.Id}\"");
        }
    
        nodeDetails.AppendLine($"\t\"{node.Id}\" [label=\"{node.Name}\"]");
    }
    
    using(StreamWriter sw = new StreamWriter(@"c:\temp\test.dot"))
    {
        sw.WriteLine("digraph G {");
        sw.Write(nodeRelationships.ToString());
        sw.Write(nodeDetails.ToString());
        sw.WriteLine("}");
    }
    

    …我可以生成以下文本文件…

    digraph G {
        "bec9439f-d4fb-4ee5-9d69-c33f54f91124" -> "79b5be71-0e01-4d0c-9640-ddfd98634b96"
        "bec9439f-d4fb-4ee5-9d69-c33f54f91124" -> "a5718293-1f93-4450-ad92-a89458d5600e"
        "a5718293-1f93-4450-ad92-a89458d5600e" -> "eaf07cbc-fd5c-4cc5-829e-166ff20b2ef9"
        "a5718293-1f93-4450-ad92-a89458d5600e" -> "7b4dbc24-6ab6-4585-bca3-95888c713f3c"
        "bec9439f-d4fb-4ee5-9d69-c33f54f91124" [label="Doe, Jane"]
        "79b5be71-0e01-4d0c-9640-ddfd98634b96" [label="Smith, Jim"]
        "a5718293-1f93-4450-ad92-a89458d5600e" [label="Jones, Bill"]
        "eaf07cbc-fd5c-4cc5-829e-166ff20b2ef9" [label="Adams, Sherri"]
        "7b4dbc24-6ab6-4585-bca3-95888c713f3c" [label="Walker, Dan"]
    }
    

    运行以下命令

    点-tpng test.dot-o test.png

    以我的文本文件(test.dot)作为输入,并生成test.png作为输出。输出如下…

    Sample output

    如果您查看dot语言的引用,您会发现这是一个简单的示例,您可以做很多事情来影响结果的外观。

    因此,您的应用程序可以生成适当的文本,并在后台使用dot创建应用程序随后显示的图像。