# التسلسلات الهرمية للبيانات: إدارة البيانات الهرمية مع EF و EF reas و PostgreSQL (عرض عام)

<!--category-- Entity Framework, PostgreSQL, EF Hierarchies -->
<datetime class="hidden">2025-12-06T09:00</datetime>

## أولاً

البيانات الهرمية هي في كل مكان في تطوير البرمجيات: التعليقات الخيطة، الرسوم البيانية التنظيمية، أنظمة الملفات، فئات المنتجات، ومناقشات المنتدى. السؤال الأبدي عن "كيف أخزن شجرة في قاعدة بيانات علاقة؟" قد طارد المطورين منذ الأيام الأولى من SQL، وبصراحة، لا يزال لا يوجد جواب واحد يجعل الجميع سعداء. [حول هذا الموضوع في عام 2004](/blog/1188)ولا تزال التحديات الأساسية كما هي اليوم.

### السبب في أن التسلسل الهرمي صعب في SQL

وهنا تكمن المشكلة الأساسية: **قواعد بيانات البيانات ذات العلاقة تفكر في مجموعات، لا في الأشجار**كما شرح جو سيلكو في كتابه الممتاز [جاري البحث في المجموعات](https://www.amazon.com/Joe-Celkos-Thinking-Sets-Management/dp/0123741378)يعمل SQL على جداول كاملة وليس صفاً فردياً.

عند كتابةك لـ SSQQL ، محرك قاعدة البيانات يعمل على **إنها عبقرية في العمليات مثل "تجد جميع الطلبات على 100" أو "تنضم العملاء إلى مشترياتهم" - هذه هي عمليات المجموعة التي تتناسب بشكل طبيعي مع كيفية عمل الجداول. النتيجة هي دائماً مجموعة مسطحة من الصفوف.

غير أن التسلسل الهرمي هو في جوهره *(م)*لكي تجد كل ذرية العقدة، تحتاج إلى:

1. جد الأطفال المباشرين
2. لكل طفل، يُعثر على *بشأنها* الأطفال
3. "تكرر حتى تجتاز كامل الأشجار"

هذا تكراري traververal لا يرسم بشكل طبيعي لوضع العمليات. لا يمكنك التعبير عن "أعطني كل الأحفاد في أي عمق" في بيان واحد بسيط SQL بدون أي منهما:

- [عمليات TE TE](https://www.postgresql.org/docs/current/queries-with.html#QUERIES-WITH-RECURSIVE) (مضافاً إلى SQLL: 1999، ولكن مكلفاً من الناحية الحسابية)
- رحلات متعددة ذهابا وإيابا إلى قاعدة البيانات
- ما يُخمّر أنّ مُسبقاً لعلاقات

كل نهج في هذه السلسلة يمثل مقايضة مختلفة بين تعقيد الكتابة، تعقيد القراءة، والتخزين، والعليا. ليس هناك غداء مجاني - أنت دائماً تقايض تكلفة واحدة مقابل أخرى. للمرجع النهائي لهذا الموضوع، انظر جو سيلكو. [الأسطور و التدرجات في SQL لـ](https://www.amazon.com/Hierarchies-Smarties-Kaufmann-Management-Systems/dp/0123877334)التي تغطي جميع هذه النُهُج بتعمق.

[TOC]

## المثال: تعليقات مُحبثة

لجعل المقارنات ملموسة، سنستخدم التعليقات الخيطية كنموذج تسلسلي - شيء تستخدمه هذه المدونات نفسها. قد يبدو هذا الخيط التعليقي كما يلي:

```mermaid
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
```

ونحن بحاجة إلى دعم هذه العمليات:

- **الحصول على جميع التعليقات للوظيفة** (بالهيكل الخيطي محفوظ)
- **احصل على كل الاسلاف** من تعليق (ممَرْلَكَلْ)
- **الحصول على جميع المنحدرين** التعليق (المشروع الفرعي)
- **إضافة تعليق جديد** (كرد على تعليق قائم)
- **حذف** (يطرح تعليقاً وجميع الردود)
- **** (يبدي تعليقاً - نادراً، لكنه ضروري أحياناً)

## النهج الخمسة

ويغطي كل نهج بالتفصيل في المادة الخاصة به، وإليكم ملخص يساعدكم على الاختيار:

---


### 1 قائمة الملاءمة (مرجع مرجعي للإحالة)

**[اقرأ المقالة الكاملة](/blog/efcore-hierarchical-data-adjacency)**

أبسط وأكثر نهج بديهي. كل صف يخزن إشارة إلى العقدة الأصلية. هو ما يصل إليه معظم المطورين لأول مرة لأنه يرسم بشكل طبيعي لكيفية تفكيرنا في التسلسل الهرمي.

**كيف يعمل:** كل تعليق لـه عـلـاقـة `ParentCommentId` لتعليقات الجذور NULL، والردود تشير إلى والديها.

**أفضل من أجل:** التسلسل الهرمي الضحل (أقل من 5-6 مستويات)، حركات شجرية متكررة، عندما تريد خصائص تصفح EF CORE للعمل بشكل طبيعي.

**المقاصات:** يتطلب الحصول على الأجداد أو أحفادهم عمليات تفاضلية متكررة أو استفسارات متعددة. بسيطة للكتابة، يمكن أن تكون بطيئة في قراءة الأشجار العميقة.

---


### 2- الميـول

**[اقرأ المقالة الكاملة](/blog/efcore-hierarchical-data-closure)**

يقوم بتخزين و تخزين كل علاقة بين سلف و من سلالة في جدول منفصل. بدلاً من معرفة العلاقات في وقت الاستعلام، نقوم بتخزينها بشكل صريح مع عمقها.

**كيف يعمل:** ألف - مستقلة `CommentClosure` ويمكن أن يتضمن التعليق 4 تحت التعليق 1 عبر التعليق 3 مدخلات: (1,4,2,3,4,1,4,1,4,4,4,0).

**أفضل من أجل:** تطبيقات قراء الثقيلة، عندما تحتاج إلى الإستفسار في الأعماق التعسفية، عندما نادراً ما تحرك الأشجار الفرعية.

**المقاصات:** أما المداخل الأكثر تعقيداً (يضاف إليها أيضاً قيود الإغلاق)، فالتخزين ينمو بتعمق، وتتطلّب شقق فرعية متحركة إغلاقات جديدة.

---


### 3 - الطريق

**[اقرأ المقالة الكاملة](/blog/efcore-hierarchical-data-path)**

يقوم بتخزين كامل السلالة كسلسلة نصية محددة. اعتبرها تخزيناً للعنوان البريدي الكامل بدلاً من مجرد اسم الشارع.

**كيف يعمل:** لكل تعليق على `Path` مثل عمود "1/3/7" بمعنى "الروت هو 1، الوالد هو 3، هذا هو 7". يمكن تقسيم الأسلاف من الخيط؛ يمكن العثور على الأحفاد مع استفسارات مماثلة.

**أفضل من أجل:** جيل فتات الخبز، عندما يُسأل الأجداد أكثر من مجرد ذرية، عندما تريد مسارات قابلة للقراءة من البشر من أجل التصحيح.

**المقاصات:** مثل الإستفسارات يمكن أن تكون بطيئة بدون الفهارس الصحيحة، المسار الأوتار لها حدود طولية، تحريك الأشجار الفرعية يتطلب تحديث جميع مسارات السلال.

---


### 4 - المجموعات المستنبتة

**[اقرأ المقالة الكاملة](/blog/efcore-hierarchical-data-nested)**

يعيّن كل نُقطة يسار و يمين أرقام من a عمق الأوّل. كلّ ذرّات له قيم. *- - - - - -* حدود الأباء

**كيف يعمل:** كان لكل تعليق على ما يلي: `Left` وقد عقد مؤتمراً بشأن `Right` تحتوي العقدة التي تحمل L=4، R=7 على جميع العقد التي يوجد فيها 4 < يساراً و يميناً > 7.

**أفضل من أجل:** كفئة الأشجار. ممتاز لـ "احصل على كامل شجرة تحتية في ترتيب العرض" إستفسارات.

**المقاصات:** الإضافات تحتاج إلى تحديث العديد من الصفوف (حوّل كل القيم إلى غرفة)، الشجر الفرعي المتحرك معقد. غير مناسب للكتابات المتكررة.

---


### 5 - مرحلة ما بعد البريدSSQL ltry

**[اقرأ المقالة الكاملة](/blog/efcore-hierarchical-data-ltree)**

postgreSQL يعمل

**كيف يعمل:** ثالثاً - `ltree` مع مسارات مثل "1-3-7". الفهارس التي تتيح كفاءة الاسلاف/استفسارات من الخلف باستخدام مشغلين مثل: `@>` وقد عقد مؤتمراً بشأن `<@`.

**أفضل من أجل:** موقعSQL فقط نشرات حيث الأداء مهم، عندما تحتاج إلى نمط مطابقة الإستفسارات، عندما تريد أفضل المسارات المادية.

**المقاصات:** PostgreSQL فقط، يضيف الاعتماد على توسيع قاعدة البيانات. ملاحظة: [نبغgsql يجري دعم دعم linQ](https://www.npgsql.org/efcore/mapping/translations.html#ltree-functions) عـن شـرـر شـر `LTree` على الرغم من أن الـ CTEs لا تزال تتطلب الخام SQL.

---


## موجز

يُدرج ما يلي: (أ) (أ) (أ) (أ) (أ) (أ) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (أ) (ب) (ب) (ب) (ب) (ب) (ب) (أ) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (أ) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (أ) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب) (ب)  
|----------|--------|---------------|-----------------|--------------|---------|-----------------|
| **** O (1) O(n) مع CTE o o O (d) مع CTE o O (1)
| **المُنْفَفَفَفَف** o O(n x d) o O (1) O (1) o O (s x d) o O (n x d) o جيد
| **مُثثثثثثثث** سين )١( سين )١(* o O (1) o O (Os) o O (d) لكل عقد من العقد o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o
| **مُنت مُز تنفيذ** o O(n) o O (1) O (1) o O (n) o الحد الأدنى o جيد o جيد o
| **لا تُغرِّر** O (1) O (1) أو O (1) أو O (1) أو O (Os) o O (d) في العقد الواحد من العقد `LTree` )( / / / /

*ن = مجموع العقدات، د = العمق، س = الحجم الفرعي*
*مع الرقم القياسي الصحيح

## مشروع مشروع مشروع

```mermaid
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
```

## الخيار العالمي الحقيقي : هذه القائمة

هذه المدوّنة تستخدم **المُنْفَفَفَفَف** الأساس المنطقي:

1. تُقرأ التعليقات على نحو أكثر تواترا بكثير مما تُقرأ
2. يجب أن نعرض تعليقاتنا المُعَسَسة بكفاءة
3. والاستفسارات عن حدود العمق مهمة بالنسبة للأداء (الحد الأقصى عند عمق 5 مستويات)
4. ونادراً ما يُنقل التعليق (يلزم أحياناً القيام بذلك)

انظر S انظر [الجزء الثاني: جدول النتائج](/blog/efcore-hierarchical-data-closure) (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة) و (بآلاف دولارات الولايات المتحدة)

## السلسلة

- **الجزء 1: لمحة عامة** (هذه المادة)
- [الجزء 1-1: قائمة الحدود](/blog/efcore-hierarchical-data-adjacency) - إشارات مرجعية بسيطة
- [الجزء الثاني: جدول النتائج](/blog/efcore-hierarchical-data-closure) - العلاقات المحسوبة من قبل
- [الجزء 1-3: الدرب المادي](/blog/efcore-hierarchical-data-path) - السلاسل
- [الجزء 1-4: المجموعات المُطرَدة](/blog/efcore-hierarchical-data-nested) - الحدود اليسارية - اليمينية
- [الجزء الأول: الشارع](/blog/efcore-hierarchical-data-ltree) - المُوسَقَرSQL مُنْطَج مُنْطَجِي
- الجزء 2: الدفعة الأولى من الدفعة الثانية من الدفعة الأولى من الدفعة الثانية من الدفعة الثانية من الدفعة الثانية من الدفعة الثانية والدرجة الثانية (قريباً قريباً)