Il existe une prise en charge des requêtes hiérarchiques dans une bibliothèque d'extensions EF populaire: https: // entityframework-extensions .net / to-self-hierarchy-list.

Je suis curieux de savoir comment ça marche sous le capot? Est-il géré par le serveur SQL, ce qui signifie que la requête est traduite en CTE (expression de table commune)?

0
Grigoryants Artem 12 mars 2021 à 17:42

1 réponse

Meilleure réponse

Clause de non-responsabilité : je suis le propriétaire des Extensions Entity Framework

Vous avez bien compris, nous utilisons en effet un CTE dans le SQL généré.

Voici à quoi ressemble le modèle SQL:

WITH
    SelfHierarchyQueryOuter AS (@(sqlMaster)),
    SelfHierarchyQueryInner AS (@(sqlHierarchy)),
    SelfHierarchyQuery AS (SELECT A.*, 0 AS ZZZ_Recursion FROM (SELECT * FROM SelfHierarchyQueryOuter) AS A 
                                    UNION ALL
                                    SELECT B.*, ZZZ_Recursion + 1 AS ZZZ_Recursion FROM  (SELECT * FROM SelfHierarchyQueryInner) AS B
                                    INNER JOIN SelfHierarchyQuery AS C ON @(keyJoins) 
                                    WHERE ZZZ_Recursion < @(maxRecursion)
                                    )

@(selectFinal)
FROM    SelfHierarchyQuery

Donc une requête comme celle-ci:

var list2 = context.EntitySimples.ToSelfHierarchyList(x => x.Parent, options => options.MaxRecursion = 5);

Générera le SQL suivant:


WITH
    SelfHierarchyQueryOuter AS (SELECT TOP 100 PERCENT  
    [Extent1].[ID] AS [ID], 
    [Extent1].[ColumnInt1] AS [ColumnInt1], 
    [Extent1].[ColumnInt2] AS [ColumnInt2], 
    [Extent1].[Parent_ID] AS [Parent_ID]
    FROM [dbo].[EntitySimple] AS [Extent1]),
    SelfHierarchyQueryInner AS (SELECT TOP 100 PERCENT  
    [Extent1].[ID] AS [ID], 
    [Extent1].[ColumnInt1] AS [ColumnInt1], 
    [Extent1].[ColumnInt2] AS [ColumnInt2], 
    [Extent1].[Parent_ID] AS [Parent_ID]
    FROM [dbo].[EntitySimple] AS [Extent1]),
    SelfHierarchyQuery AS (SELECT A.*, 0 AS ZZZ_Recursion FROM (SELECT * FROM SelfHierarchyQueryOuter) AS A 
                                    UNION ALL
                                    SELECT B.*, ZZZ_Recursion + 1 AS ZZZ_Recursion FROM  (SELECT * FROM SelfHierarchyQueryInner) AS B
                                    INNER JOIN SelfHierarchyQuery AS C ON C.[Parent_ID] = B.[ID] 
                                    WHERE ZZZ_Recursion < 5
                                    )

SELECT *
FROM    SelfHierarchyQuery

Rien de "spécial" ici, juste en utilisant une grande fonctionnalité du CTE pour le faire fonctionner.

1
Jonathan Magnan 13 mars 2021 à 18:44