web-dev-qa-db-fra.com

chargement d'une hiérarchie complète à partir d'une table d'auto-référencement avec EntityFramework.Core

Explication des raisons pour lesquelles cette question diffère: EF - multiple permet de charger rapidement des données hiérarchiques. Mauvaise pratique?

  1. le double possible est une question d’opinion, s’il s’agit d’une mauvaise pratique ou non, alors que ma question tend à obtenir la solution technique pour le faire, indépendamment de l’opinion, qu’il s’agisse d’une bonne pratique ou non. Je laisse cette décision au propriétaire du produit, à l'ingénieur des exigences, au chef de projet et au client qui souhaite cette fonctionnalité.
  2. Les réponses fournies expliquent soit pourquoi il s’agit d’une mauvaise pratique, soit utilisent une approche qui ne fonctionne pas pour moi (utiliser Include () et ThenInclude () produit une profondeur codée en dur alors que j’ai besoin d’une profondeur flexible).

Dans le projet actuel (une API Web .NET principale), j'essaie de charger une hiérarchie à partir d'une table d'auto-référencement.

Après avoir beaucoup cherché sur Google, j'ai été surpris qu'une telle tâche (que je pensais être triviale) ne semble pas être anodine.

Eh bien, j'ai cette table pour former ma hiérarchie:


CREATE TABLE [dbo].[Hierarchy] (
    [Id]        INT           IDENTITY (1, 1) NOT NULL,
    [Parent_Id] INT           NULL,
    [Name]      NVARCHAR (50) NOT NULL,
    PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_Hierarchy_Hierarchy] FOREIGN KEY ([Parent_Id]) REFERENCES [dbo].[Hierarchy] ([Id])
);

Dans l’API Web, j’essaie de renvoyer la hiérarchie complète. Une chose peut-être spéciale (qui pourrait aider) est le fait que je veuille charger le tableau complet.

Je sais aussi que je pourrais utiliser le chargement rapide et la propriété de navigation (Parent et InverseParent pour les enfants)


_dbContext.Hierarchy.Include(h => h.InverseParent).ThenInclude(h => h.InverseParent)...

Le problème, c'est que cela chargerait une profondeur codée en dur (par exemple, six niveaux si j'utilise 1 Include () et 5 ThenInclude ()), mais ma hiérarchie a une profondeur flexible.

Quelqu'un peut-il m'aider en me donnant du code sur la manière de charger la table complète (par exemple, en mémoire dans un scénario optimal avec 1 appel de base de données), puis d'obliger la méthode à renvoyer la hiérarchie complète?

7
monty

En fait, charger la hiérarchie entière est assez facile grâce à ce qu'on appelle EF (Core) relation de correction.

Disons que nous avons le modèle suivant:

public class Hierarchy
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Hierarchy Parent { get; set; }
    public ICollection<Hierarchy> Children { get; set; }
}

Puis le code suivant

var hierarchy = db.Hierarchy.Include(e => e.Children).ToList();

chargera toute la hiérarchie avec les propriétés Parent et Children correctement remplies.

Le problème décrit dans les publications référencées survient lorsque vous ne devez charger qu'une partie de la hiérarchie, ce qui est difficile en raison de l'absence de support CTE semblable à celui de LINQ.

16
Ivan Stoev

J'ai construit une procédure stockée pour obtenir tous les enfants de tous les niveaux en utilisant un cte récursif Procédure stockée pour obtenir tous les ids des enfants de tout niveau de table d'auto-référencement utilisant Entity Framework et un cte récursif

1
Simple Code