2

我们想在 SQL Server 2012 中存储一个简单的 Web 导航菜单。这将为多个客户端完成,这就是我们需要存储它的原因。菜单项也需要有顺序,因此可以按照客户的需要对其进行排序。我一直在阅读 SQL Server 的 HierarchyId 数据类型,但我发现的几乎所有教程都使用员工或公司层次结构的示例,顶部有一个根节点。经过数小时的阅读和测试,我对HierarchyId 可能不是简单的链接导航菜单的最佳工具感到震惊。我有这种感觉吗?

我注意到 HierarchyId 让我担心的主要一点是,你只能有一个带有 HierarchyId 的根节点。但是有了导航菜单,显然有多个可以有子级的顶级“根节点”。而且由于根节点没有顺序(它们只是“/”),我们的客户将无法在其顶级菜单链接中移动。

因此,显而易见的选择是拥有一个虚拟根节点,并将所有顶级菜单链接都放在该根节点下。但是根据这个 SO question,marc_s 和 Jeremy 似乎不寻常(或者不是根据 HierarchyId 的正常用法)创建一个人造的“über-root”节点,只是为了拥有多个一级节点。并且通过执行这个“über-root”节点,我是不是也抛弃了 SQL 服务器的 GetLevel() 函数,因为“顶级”节点现在将显示为级别 1 而不是 0?

我正在考虑只在每一行中存储一个 ParentId 并在 C# 中使用递归来构建菜单层次结构。我这样做会错吗?HierarchyId 数据类型是否真的适用于这种情况,而我只是遗漏了一些东西?

4

1 回答 1

4

我不认为我会担心有一个“虚拟”根节点——你显然不必显示它(在某些方法中,如果你小心的话,你甚至不必将根节点存储在数据库中与您的查询)。

任何有根树都需要一个根,并且任何有根树都可以分解成单独的有根树,即

          A                
         / \
        B   C       =>   B        C
       / \   \          / \        \
      D   E   F        D   E        F

所以换句话说,你总是可以通过引入一个共同的根来组合多棵树。

我相信您问题的核心是如何将分层数据存储在数据库中。

有以下三种“经典”方式:

  1. 邻接列表”(我相信这是您在提到“在 C# 中使用递归”时所暗示的
  2. 分层路径”(这是您使用 sql server 层次结构 id 得到的)
  3. 嵌套集”(包含基于集合的 sql 方法)

其中任何一个都适合存储分层数据——它们在不同类型的查询的性能和表示的易用性方面有不同的权衡。

参考:

  1. SQL 中的树(作者:Joe Celko)
  2. 层次结构:将邻接列表转换为嵌套集
  3. 使用嵌套集提高层次结构性能
  4. 嵌套集模型
于 2014-04-19T20:11:16.400 回答