Utilisez Linq pour interroger des nœuds terminaux / feuilles dans un modèle de table hiérarchique / composite

StackOverflow https://stackoverflow.com/questions/414945

Question

J'ai une table d'auto-référencement avec un ID, un Nom de catégorie et un ParentId. Il s'agit d'un scénario typique d'une table hiérarchique de catégories pouvant être elles-mêmes divisées en catégories que les experts en base de données me disent s'appeler le modèle d'adjacence.

Ce que je veux, c’est utiliser Linq to SQL pour interroger des sous-catégories qui ne sont liées à aucune autre sous-catégorie, c’est-à-dire qu’elles sont des nœuds terminaux immédiats d’une catégorie ou d’une sous-catégorie donnée.

La partie la plus facile que j'ai eue, c'est-à-dire les sous-catégories. Presque embarrassé de mettre le code ici. Mais nous aimons voir le code.

IList<Categories> subcategories = context.Where( c => c.ParentId == 1).ToList();  

Mais le réduire aux catégories sans sous-catégories me fait changer les choses. Toute aide serait la bienvenue.

Merci pour votre aide. Jeff

UPDATE ** Il semblerait que cela fonctionne, mais si quelqu'un pouvait confirmer qu'il est "correct" Je vous en serais reconnaissant. Donc, si je veux des nœuds d'extrémité dans une catégorie avec Id = 1, je le ferais:

Categories.Where( c => !c.Children.Any ( d => d.ParentId == c.Id)).Where( e => e.ParentId == 1) 

" Enfants " est le nom que Linq donne à l’auto-référencement.

Était-ce utile?

La solution

Votre solution est correcte car la méthode Any () se traduit par sql "EXISTS ()". une fonction et ! c.Children.Any (d = > d.ParentId == c.Id)) se traduit par une clause SQL similaire à NOT EXISTS (SELECT * FROM Catégories WHERE ParentID = outerRef .ID)

Une autre façon de le faire consiste à utiliser Count :

Categories.Where( c => c.Children.Count(d => d.ParentId == c.Id) == 0).Where( e => e.ParentId == 1)

Mais généralement, EXISTS () est préféré à COUNT () dans sql (pour des raisons de performances). La solution avec Any () doit donc être la bonne.

Autres conseils

Je pense que si je comprends bien votre question, vous essayez d'obtenir tous les éléments Child qui n'ont pas d'enfant propre. Cette requête auto joint la table sur elle-même pour tester si le nœud est utilisé en tant que parent. Si ce n’est pas le cas, il est affiché dans le résultat.

Je ne suis pas sûr que cela fonctionne car je n'ai rien pour le tester ...

   (from c in context
    join cc in context on c.id equals cc.parentid into temp
    from t in temp.DefaultIfEmpty()
    where t == null
    select c).ToList()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top