Comment faire une charge récursive avec le framework Entity?

entity entity-framework load recursion

Question

J'ai une arborescence dans la table DB avec TreeNodes. la table a nodeId, parentId et parameterId. dans EF, la structure est semblable à TreeNode.Children où chaque enfant est un TreeNode ... J'ai aussi une table Tree avec contient id, name et rootNodeId.

À la fin de la journée, je voudrais charger l’arbre dans un TreeView mais je ne vois pas comment le charger en une fois. J'ai essayé:

var trees = from t in context.TreeSet.Include("Root").Include("Root.Children").Include("Root.Children.Parameter")
        .Include("Root.Children.Children")
                        where t.ID == id
                        select t;

Cela me fera les 2 premières générations mais pas plus. Comment charger tout l'arbre avec toutes les générations et les données supplémentaires?

Réponse populaire

J'ai eu ce problème récemment et suis tombé sur cette question après avoir trouvé un moyen simple d'obtenir des résultats. J'ai fourni une modification à la réponse de Craig, fournissant une quatrième méthode, mais les décideurs en ont décidé autrement. Ça me va :)

Ma question / réponse originale peut être trouvée ici.

Cela fonctionne tant que vos éléments dans la table savent tous à quel arbre ils appartiennent (dans votre cas, cela ressemble à cela: t.ID ). Cela dit, vous ne savez pas exactement quelles entités sont en jeu, mais même si vous en avez plusieurs, vous devez avoir un FK dans l'entité Children si ce n'est pas un TreeSet

En gros, n'utilisez pas Include() :

var query = from t in context.TreeSet
            where t.ID == id
            select t;

// if TreeSet.Children is a different entity:
var query = from c in context.TreeSetChildren
            // guessing the FK property TreeSetID
            where c.TreeSetID == id
            select c;

Cela ramènera TOUS les éléments de l'arbre et les mettra tous à la racine de la collection. À ce stade, votre jeu de résultats ressemblera à ceci:

-- Item1
   -- Item2
      -- Item3
-- Item4
   -- Item5
-- Item2
-- Item3
-- Item5

Puisque vous voulez probablement que vos entités ne sortent d'EF que de manière hiérarchique, ce n'est pas ce que vous voulez, n'est-ce pas?

.. alors, exclure les descendants présents au niveau racine:

Heureusement, étant donné que vous avez des propriétés de navigation dans votre modèle, les collections d'entités enfants seront toujours remplies, comme l'illustre l'illustration du jeu de résultats ci-dessus. En effectuant une itération manuelle sur le jeu de résultats à l'aide d'une boucle foreach() et en ajoutant ces éléments racine à une new List<TreeSet>() , vous obtenez maintenant une liste avec les éléments racine et tous les descendants imbriqués correctement.

Si vos arbres deviennent volumineux et que les performances posent un problème, vous pouvez trier votre ensemble de retour ParentID par ParentID (c'est Nullable , n'est-ce pas?), De sorte que tous les éléments racine soient en premier. Itérez et ajoutez comme avant, mais sortez de la boucle une fois que vous arrivez à une boucle non nulle.

var subset = query
     // execute the query against the DB
     .ToList()
     // filter out non-root-items
     .Where(x => !x.ParentId.HasValue);

Et maintenant, le subset - subset ressemblera à ceci:

-- Item1
   -- Item2
      -- Item3
-- Item4
   -- Item5



À propos des solutions de Craig:

  1. Vous ne voulez vraiment pas utiliser le chargement paresseux pour cela! Une conception construite autour de la nécessité d'interrogation n + 1 sera un atout majeur pour les performances.
  2. ********* ( Eh bien, pour être juste, si vous autorisez un utilisateur à explorer de manière sélective l'arborescence, cela pourrait être approprié. N'utilisez simplement pas le chargement paresseux pour les obtenir tous. -front !! )

  3. Je n'ai jamais essayé les éléments d'ensemble imbriqués, et je ne recommanderais pas non plus de modifier la configuration EF pour que cela fonctionne, étant donné qu'il existe une solution beaucoup plus simple.

  4. Une autre suggestion raisonnable consiste à créer une vue de base de données fournissant une liaison automatique, puis à mapper cette vue sur une table intermédiaire joint / link / m2m. Personnellement, j’ai trouvé cette solution plus compliquée que nécessaire, mais elle a probablement ses utilités.



Related

Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow