2009-01-05 10 views
3

J'ai une table auto-référencée avec un ID, un nom de catégorie et un ID parent. C'est un scénario typique d'une table hiérarchique de catégories qui peuvent elles-mêmes être divisées en catégories que les experts DB me disent s'appeler le modèle de contiguïté. Ce que je veux, c'est utiliser Linq to SQL pour rechercher des sous-catégories qui ne sont elles-mêmes liées à aucune autre sous-catégorie, c'est-à-dire qu'elles sont des noeuds-feuilles immédiats d'une catégorie ou sous-catégorie donnée.Utilisation de Linq to Query pour les nœuds terminaux/Leaf dans le modèle hiérarchique/composite

La partie facile, j'ai, qui obtient juste les sous-catégories. Presque gêné de mettre le code ici. Mais nous aimons voir le code ..

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

Mais rétrécissant à des catégories sans sous-catégories me tournant autour. Toute aide serait très appréciée.

Merci pour votre aide. Jeff

MISE À JOUR ** Il semblerait que cela fonctionne, mais si quelqu'un pouvait confirmer que c'est "correct", je serais reconnaissant. Donc, si je veux nœuds feuilles dans une catégorie avec Id = 1, je ferais ceci:

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

« Enfants » est le nom Linq donne l'association auto-référencement.

+0

Il semblerait que cela fonctionne, mais si quelqu'un pouvait confirmer que c'est "correct", je serais reconnaissant. Donc, si je veux des nœuds feuille sous une catégorie avec Id = 1, je ferais ceci: Catégories.Où (c =>! C.Children.Any (d => d.ParentId == c.Id)). Où (e => e.ParentId == 1) – jlembke

Répondre

2

Votre solution est correcte parce que la méthode Any(), se traduit par sql « exists() » fonction et !c.Children.Any (d => d.ParentId == c.Id)) se traduit par une clause SQL similaire à NOT EXISTS (SELECT * FROM Categories WHERE ParentID = outerRef.ID)

une autre façon de le faire est d'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 être la bonne.

0

Je pense que si je comprends bien votre question, vous essayez d'obtenir tous les éléments enfants qui n'ont pas d'enfants ... cette requête se joint à la table sur elle-même pour tester si le nœud est utilisé comme parent, si ce n'est pas alors il est affiché dans le résultat.

Je ne sais pas si cela fonctionne comme je l'ai rien à tester sur ...

(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()