2010-06-18 8 views
0

Par souci de simplicité, un objet « section » contient les propriétés suivantes:LINQ pour déterminer si les enfants existent

SectionId 
ParentSectionId 
Name 

J'ai actuellement le code LINQ ci-dessous pour obtenir des sections de l'enfant d'une section donnée:

List<Section> sections = SectionCache.GetAllSections(); 

sections.AsQueryable().Where(s => s.ParentSectionId == 10); 

Cela me donne tous les enfants de la section avec une sectionId de 10 (encore une fois, pour la simplicité), mais j'ai besoin de développer cela pour inclure seulement les sections qui ont eux-mêmes des enfants. Dans SQL, je pourrais faire quelque chose comme ceci:

SELECT  Section.SectionId, 
      Section.ParentSectionId, 
      Section.Name 
FROM  Section 
INNER JOIN Section children ON children.ParentSectionId = Section.SectionId 
WHERE  Section.ParentSectionId = 10 
GROUP BY Section.SectionId, 
      Section.ParentSectionId, 
      Section.Name 
HAVING  COUNT(children.SectionId) > 0 

Comment puis-je parvenir à LINQ/quelle est la meilleure façon d'y parvenir avec LINQ?

Merci

+0

Pas besoin d'appeler AsQueryable. Cela ne fait rien. –

Répondre

2

Voici quelques façons de le faire (ce sont à peu près identiques)

IEnumerable<Section> query = 
    sections.Where(s => 
    sections.Any(c => s.SectionId = c.ParentSectionId)) 
); 

IEnumerable<Section> query = 
    from s in sections 
    where (
    from c in sections 
    where c.ParentSectionId == s.SectionId) 
    select c).Any() 
    select s; 

Ou de façon plus optimale:

ILookup<int, Section> childLookup = 
    sections.ToLookup(c => c.ParentSectionId); 
IEnumerable<Section> query = 
    sections.Where(s => childLookup[s.SectionId].Any()); 

Ensuite, il y a la technique de GroupJoin, qui devrait être assez efficace aussi:

IEnumerable<Section> query = 
    from s in sections 
    join c in sections 
    on s.SectionId equals c.ParentSectionId 
    into children 
    where children.Any() 
    select s; 
+0

Merci pour la réponse rapide - parfait! –

0

je préfère la syntaxe LINQ SQL. C'est plus lisible que celui qui parle couramment. :-)

 var sections = SectionCache.GetAllSections().AsQueryable(); 
     var filteredSections = from s in sections 
           let cc = (from c in sections 
              where (c.ParentSectionId == s.SectionId) 
              select c).Count() 
           where (s.ParentSectionId == 10) && (cc > 0) 
           select s; 
1

Voici quelques idées si pour vous, si je lis vos exigences droite

// one method 
var query = from section in sections 
      where sections.Any(s => s.ParentSectionId == section.SectionId) 
      select section; 

// another method 
var query2 = (from section in sections 
       join child in sections 
       on section.SectionId equals child.ParentSectionId 
       select section).Distinct(); 

Avec une liste peuplée de cette manière

List<Section> sections = new List<Section>() 
{ 
    new Section() { SectionId = 1, ParentSectionId = 0, Name = "Alpha" }, 
    new Section() { SectionId = 2, ParentSectionId = 0, Name = "Bravo" }, 
    new Section() { SectionId = 3, ParentSectionId = 0, Name = "Charlie" }, 
    new Section() { SectionId = 4, ParentSectionId = 1, Name = "Apple" }, 
    new Section() { SectionId = 5, ParentSectionId = 2, Name = "Banana" }, 
    new Section() { SectionId = 6, ParentSectionId = 4, Name = "Aardvark" }, 
    new Section() { SectionId = 7, ParentSectionId = 4, Name = "Antelope" } 
}; 

Les requêtes retourneraient Alpha, Bravo, et Apple.

0
 List<Section> sections = new List<Section>(); 
     sections.Add(new Section { SectionId = 1, ParentSectionId = 0, Name ="S1" }); 
     sections.Add(new Section { SectionId = 2, ParentSectionId = 1, Name = "S2" }); 
     sections.Add(new Section { SectionId = 3, ParentSectionId = 1, Name ="S3" }); 
     sections.Add(new Section { SectionId = 4, ParentSectionId = 2, Name ="S4" }); 
     sections.Add(new Section { SectionId = 5, ParentSectionId = 2, Name ="S5" }); 

     var result = sections.GroupJoin(sections, p => p.SectionId, chld => chld.ParentSectionId, (p, chld) => new { Parent = p, Children = chld }) 
          .Where(g => g.Children.Any()) 
          .Select(g => g.Parent); 
Questions connexes