Back to "以 EF 核心和 PostgreSQL @(}Overview) 管理等级数据"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

EF Hierarchies Entity Framework PostgreSQL

以 EF 核心和 PostgreSQL @(}Overview) 管理等级数据

Saturday, 06 December 2025

一. 导言导言 导言 导言 导言

在软件开发中,等级数据无处不在 :}(线性评论),}组织图表 *,}文件系统 <,}产品类别,}♪和论坛讨论 有关这个话题的首篇文章,以及基本挑战依然如故,

为何SQL的等级结构很困难

基本问题在于: 相关数据库在数组中思考@, @% 而不是树Joe Celko在他的杰出著作中解释, 以一组思考,SQL在整张表格上运行 ,}不是单行=.

当您写入 SQL 查询\ ,}数据库引擎运行时 一组行100"或"join客户购买的订单

但等级制度是内在的 连续循环找到一个节点的所有子孙 您需要到 :

  1. 寻找直系子女
  2. 每个孩子都能找到 他们的 儿童子女
  3. 重复一遍,直到你踏遍了整个树下

此递归的十字路由 @ ' @ t映射为自然设置操作@ MS K1} 您可以在任何深度表达 @ I"} 将我所有的子孙都递解成一个单一的\ ,简单的 SQL 语句, 其中不包含 @ MPK6}

  • 递续 CTE (+SQL:1999,+但计算成本昂贵
  • 多次往返访问数据库
  • 预先计算关系的聪明的去正常化

在本系列中,每种方法都代表了一种不同的交易 -Q 。 在复杂的写法\ ,Q 读起复杂的事情\ MS K2QQ 和存储的间接费用\ MSSK3Q 之间有一个不同的交易。 没有免费的午餐\ I-Q你='ZARE总是以一个价格换另一个#.}请见Joe Celko'Qs. SQL 中用于智能的树和层次深入地涵盖所有这些方针的,*}.

示例:串列注释

要比较混凝土@, @ we'}将使用线性评论作为我们运行中的示例 @-这个博客就使用了。 批注线索可能看起来像此:}

flowchart TD
    subgraph Post["Post: How to Deploy Docker Containers"]
        C1["Comment 1: Great article!<br/>depth 0"]
        C2["Comment 2: Thanks!<br/>depth 1"]
        C3["Comment 3: Very helpful indeed<br/>depth 1"]
        C4["Comment 4: Agreed!<br/>depth 2"]
        C5["Comment 5: What about Kubernetes?<br/>depth 0"]
        C6["Comment 6: That's covered in part 2<br/>depth 1"]
    end

    C1 --> C2
    C1 --> C3
    C3 --> C4
    C5 --> C6

    style Post stroke:#10b981,stroke-width:2px
    style C1 stroke:#6366f1,stroke-width:2px
    style C2 stroke:#8b5cf6,stroke-width:2px
    style C3 stroke:#8b5cf6,stroke-width:2px
    style C4 stroke:#a855f7,stroke-width:2px
    style C5 stroke:#6366f1,stroke-width:2px
    style C6 stroke:#8b5cf6,stroke-width:2px

我们需要支持这些行动

  • 获取所有文章的备注 @(#有线条结构保存 #)#
  • 把所有祖先都带走 @(breadcrumb track)}评论中的评论
  • 把所有后代都带走 @(_entire subtree@)}评论中的评论
  • 添加新注释 @( 作为对现有评论的回复@)
  • 删除子树 @(remove 一项评论和所有答复@)
  • 移动子树 @(@ recrown a 批注 *%s K1}稀有的,}但有时需要

五方针

每种方针都在其文章中详细论述,


-=YTET -伊甸园字幕组=- 翻译:

阅读整条

最简单和最直观的方法.每个行商店都引用其父节点@."It'" 大多数开发者首先达到什么目的, 因为它自然地映射到我们对等级的思考方式.

如何运作? 每条评论均无效 ParentCommentId “.” 列中根注有 NULL=,}回答指向他们的父@.}

最好的为: 当您想要 EF Core@' @%s 导航属性自然工作时, shall 级别为 @ 5-6 @ level@ MS K2 @ 经常在子树下移动\ , @

**交易 ** 要获得祖先或后代,需要循环性幼儿保育或多个查询@. 简单写 @, 读深树可能较慢@MS K2


* 2. 关闭表

阅读整条

预估并存储所有祖先的子孙关系, 而不是在查询时间找到对方的关系@,}我们直接保存他们的深度 @.}

如何运作? A 单独一 CommentClosure 在“1”评论下, Comment@3将包含以下条目: @:+Q(1,4,2), @ @#(3,4,1),_Z(4,4,0).}

最好的为: 当您在任意深处需要查询时, 当您很少移动子树@ . k4\ 时, read -\ hiarvy applications\ MS K1\

**交易 ** 更复杂的插入@ ( @% 必须添加关闭条目@ I),} 储存随着深度的增加而增长 *\ MS K2# 移动子树需要重建关闭@ MPK3}


3. 定義路徑

阅读整条

将完整的祖先储存为定界的字符串 @. 把它视为存储完整邮政地址,而不仅仅是街道名@.

如何运作? 每条评论都有: Path 如 {"1/3/7"} 列, 意思是"} root is @1,} 父系是 这是7".} 祖先可以从字符串@;} 子孫中解析 。

最好的为: 当对祖先的询问比后代多时... ..."," 当你想要人类的时候..."-"可读调试路径 . t

**交易 ** 查询要慢一点, 没有正确的索引@ , @ 路径字符串有长度限制 @ MS K1 @ 移动子树需要更新所有后人路径@ I. @


4.+Nasted 套件

阅读整条

从深度中指定每个左节点和右边边界号@ - @ 第一次跨度 @ MS K1}所有后代都有价值 之间 父+'%s 边框\ .}

如何运作? 每项评论的评论 Left 和 Right 值Q. 与 L=4, RMS K2 的節点包含所有节点, 其中在 & 4 @\ < 左侧和右侧@< @ @ @\7. 后代端点中找到简单的范围查询@MS K7}

最好的为: 读取@ - @ hheavy,} 写下 @ MS K2 @ rarely 假想類似類型樹的區域@ I.} 非常好, @ MPK4} 以顯示的順序將整個子串按下方的排列 * " question\ .}

**交易 ** 插入需要更新很多行@( translate all value 以便让房间 @),}移动子树复杂 *. 不适合经常写入_.}


5. PostgreSQL 一棵树

阅读整条

PostgreSQL'%s 本地的等级数据扩展@. 类似已实现路径,但有数据库{-} 级别优化和强势模式匹配.

如何运作? 用途和用途 ltree 具有像 @"1.3.7". GiST 索引等路径的数据类型,使使用操作员这样的子民查询能够实现高效的祖先{/} @> 和 <@.

最好的为: PostgreSQL-}只允许在性能很重要的地方部署@ ,}当您需要模式匹配查询时 @ MS K2} 当您想要最佳的已实现路径\ .}

**交易 ** PostgreSQL @ MSKK0 @ 仅@ just\ MS K1} 添加数据库扩展依赖性@ . notte @ MPK3 Npgsql 服务提供商支持 LINQ 翻译 树的果实, LTree 类型@, @}虽然循环 CTE仍然需要原始 SQL.}


比较对比摘要

Q 移动子树 MS K5Q 存储 @ EF核心支持 # #
相邻名单 和CTE OO MS K6D)Q 与CTE O NSK9
审结表 @ @ O(d) @ @ @ I O#(1) @ ( OMS K6) @ NSK7 O}(s x d□)* * MSk9QQQZOO(nxd) 好?
定文件路径 MSKOOO O(1) NSK2 O(1)* OO(1)QO MS K2ZO I(AS)Q OMSOK6QD每个節点 MSKO8}好的
括号集 @ @ OQ(n) @ @ I OO(1) @ ( OQ(1)) MS K7 OZ(N}) @ Minimal@ 好□ #
树叶 O OO) O(D)+每个节点 @ +好~( LTree 类型@) @ @% @%

n= 總結節點MS K1 d= 深度 , s @= 子樹的大小 *使用正确的索引

决策流程图

flowchart TD
    Start([Start]) --> Q1{Shallow tree?<br/>< 5 levels}
    Q1 -->|Yes| Q2{Need EF Core<br/>navigation properties?}
    Q2 -->|Yes| AL[Adjacency List]
    Q2 -->|No| Q3{Performance<br/>critical?}
    Q3 -->|No| AL
    Q3 -->|Yes| MP[Materialised Path]

    Q1 -->|No| Q4{Read-heavy?}
    Q4 -->|Yes| Q5{Writes rare?}
    Q5 -->|Yes| NS[Nested Sets]
    Q5 -->|No| CT[Closure Table]

    Q4 -->|No| Q6{PostgreSQL only?}
    Q6 -->|Yes| LT[ltree]
    Q6 -->|No| Q7{Need breadcrumbs?}
    Q7 -->|Yes| MP
    Q7 -->|No| CT

    style Start stroke:#10b981,stroke-width:2px
    style AL stroke:#6366f1,stroke-width:2px
    style MP stroke:#8b5cf6,stroke-width:2px
    style NS stroke:#ec4899,stroke-width:2px
    style CT stroke:#f59e0b,stroke-width:2px
    style LT stroke:#14b8a6,stroke-width:2px

真实的-#World choice_:}本博客

这个博客使用 审结表 供评论用的“.”方法

  1. 阅读意见的次数远多于书面
  2. 我们需要高效显示嵌套的批注线索
  3. 深度@- @% 限制查询对性能很重要 @ (_ @ we 上限为 @ I5# 深层 @ MPK3}
  4. 移动备注是罕见的 @( } moder 偶尔需要做此@ )_

见见 缩略语 完整执行细节@. @%

系列导航

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.