一种从邻接模型+嵌套集模型(MPTT)绘制树层次结构的方法
A way to draw tree hierarchy from the Adjacency Model + Nested Sets Model (MPTT)
我有一个带有 SQL 服务器数据库的 .NET Core 2.2 应用程序,我正在使用邻接模型 + 嵌套集模型存储用户的层次结构。我正在使用 EF 核心。我的域如下所示:
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
我想将这个结构显示为一些树结构图形。有没有人对此有一些想法或工作示例?
我过去使用的一种方法是将一些繁重的工作转移到外部框架,如 Graphviz。您可以让您的应用程序生成一个文本文件,该文件由名为 "dot" 的实用程序处理以生成图形。优点是开源,使用广泛,cross-platform。缺点是让图表完全按照您想要的方式显示的语法可能会造成混淆。这是我使用您的架构创建的示例。
首先,我创建了一个对 return 记录及其父项的递归查询。我用名字填充它,就好像它是一个组织结构图一样。如果你想试验,你可以找到 fiddle 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"]
}
运行下面的命令
dot -Tpng test.dot -o test.png
将我的文本文件 (test.dot) 作为输入并生成 test.png 作为输出。输出看起来像这样...
如果您查看点语言的参考,您会发现这是一个 bare-bones 示例,您可以做很多事情来影响结果的外观。
因此,您的应用程序可以生成适当的文本并在幕后使用点来创建您的应用程序随后显示的图像。
我有一个带有 SQL 服务器数据库的 .NET Core 2.2 应用程序,我正在使用邻接模型 + 嵌套集模型存储用户的层次结构。我正在使用 EF 核心。我的域如下所示:
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
我想将这个结构显示为一些树结构图形。有没有人对此有一些想法或工作示例?
我过去使用的一种方法是将一些繁重的工作转移到外部框架,如 Graphviz。您可以让您的应用程序生成一个文本文件,该文件由名为 "dot" 的实用程序处理以生成图形。优点是开源,使用广泛,cross-platform。缺点是让图表完全按照您想要的方式显示的语法可能会造成混淆。这是我使用您的架构创建的示例。
首先,我创建了一个对 return 记录及其父项的递归查询。我用名字填充它,就好像它是一个组织结构图一样。如果你想试验,你可以找到 fiddle 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"]
}
运行下面的命令
dot -Tpng test.dot -o test.png
将我的文本文件 (test.dot) 作为输入并生成 test.png 作为输出。输出看起来像这样...
如果您查看点语言的参考,您会发现这是一个 bare-bones 示例,您可以做很多事情来影响结果的外观。
因此,您的应用程序可以生成适当的文本并在幕后使用点来创建您的应用程序随后显示的图像。