Utilizzare Linq per eseguire query per nodi terminali / foglia nel modello di tabella gerarchica / composito

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

Domanda

Ho una tabella autoreferenziale con ID, CategoryName e ParentId. È uno scenario tipico di una tabella gerarchica di categorie che possono essere divise in categorie che gli esperti di DB mi dicono che è chiamato modello di adiacenza.

Quello che voglio è usare Linq to SQL per cercare sottocategorie che a loro volta non sono correlate ad altre sottocategorie, cioè sono nodi foglia immediati di una determinata categoria o sottocategoria.

La parte facile, ho capito, è solo ottenere le sottocategorie. Quasi imbarazzato di inserire qui il codice. Ma ci piace vedere il codice ..

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

Ma restringerlo a categorie senza sottocategorie mi sta trasformando. Qualsiasi aiuto sarebbe molto apprezzato.

Grazie per l'aiuto. Jeff

UPDATE ** Sembrerebbe che funzioni, ma se qualcuno potesse confermare che è "corretto" Le sarei grato. Quindi, se voglio nodi foglia in una categoria con Id = 1, farei questo:

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

" Bambini " è il nome che Linq fornisce all'associazione autoreferenziale.

È stato utile?

Soluzione

La tua soluzione è corretta poiché il metodo Any () si traduce in sql " EXISTS () " funzione e ! c.Children.Any (d = > d.ParentId == c.Id)) si traduce in una clausola sql simile a NON ESISTE (SELEZIONA * DA Categorie DOVE ParentID = outerRef .ID)

Un altro modo per farlo è usare Count :

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

Ma di solito EXISTS () è preferito a COUNT () in sql (per motivi di prestazioni), quindi la soluzione con Any () dovrebbe essere quella giusta.

Altri suggerimenti

Penso che se capisco correttamente la tua domanda stai cercando di ottenere tutti gli elementi figlio che non hanno figli di loro ... questa query si unisce alla tabella su se stessa per verificare se il nodo viene usato come genitore , in caso contrario, viene visualizzato nel risultato.

Non sono sicuro che funzioni perché non ho nulla su cui testarlo ...

   (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()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top