2008-10-30 23 views
30

Zakładając tabelę tagów jak StackOverflow tagów pytanie:"Najpopularniejsza" GROUP BY w LINQ?

TagID (bigint) QuestionID (bigint) Tag (varchar)

Co jest najbardziej skutecznym sposobem, aby uzyskać 25 najbardziej używane tagi za pomocą LINQ? W SQL prosty GROUP BY zrobi:

SELECT Tag, COUNT(Tag) FROM Tags GROUP BY Tag 

Pisałem jakiś LINQ to działa:

var groups = from t in DataContext.Tags 
      group t by t.Tag into g 
      select new { Tag = g.Key, Frequency = g.Count() }; 
return groups.OrderByDescending(g => g.Frequency).Take(25); 

odczuwalna, naprawdę? Czy to nie jest mega-gadatliwe? Smutne jest to, że robię to, aby zapisać ogromną liczbę zapytań, ponieważ moje obiekty Tag zawierają już właściwość Frequency, która w innym przypadku musiałaby sprawdzać w bazie danych dla każdego tagu, jeśli faktycznie korzystałam z tej właściwości.

Więc następnie zanalizować te anonimowe typy powrotem do obiektów Tag:

groups.OrderByDescending(g => g.Frequency).Take(25).ToList().ForEach(t => tags.Add(new Tag() 
{ 
    Tag = t.Tag, 
    Frequency = t.Frequency 
})); 

jestem nowicjuszem LINQ, a to nie wydaje się słuszne. Proszę, pokaż mi, jak to naprawdę się stało.

+0

wierzę swój SQL powinno być 'SELECT Tag, COUNT (Tag) FROM Tags GROUP BY tag ORDER BY COUNT (Tag) DESC FETCH PIERWSZY TYLKO 25 RZECZYWISTYCH', które nie powodują, że Linq wygląda tak źle. – NetMage

Odpowiedz

10

Jestem prawie pewien, że masz rację. I SQL, który generuje i wysyła LINQ do twojej bazy danych, będzie wyglądać tak, jak SQL, z którego zacząłeś, więc podczas pisania trochę więcej, twoja baza danych nie wykonuje więcej pracy.

24

Jeśli chcesz obiektów Tag, dlaczego nie utworzyć je bezpośrednio z kwerendy Linq?

var groups = from t in DataContext.Tags 
      group t by t.Tag into g 
      select new Tag() { Tag = g.Key, Frequency = g.Count() }; 

return groups.OrderByDescending(g => g.Frequency).Take(25); 
+0

Aha! Tego właśnie mi brakowało, dzięki! – tags2k

+0

Co więcej, otrzymałem "wyraźną konstrukcję typu jednostki w zapytaniu nie jest dozwolone". Wydaje się, że nie możesz! – tags2k

+0

Podejrzewam, że to dlatego, że Tag jest typem kontekstu danych - na pewno można to zrobić z innymi typami, ale Linq najwyraźniej próbuje chronić cię przed tworzeniem instancji Tag, które nie odpowiadają elementom kontekstu danych. – GalacticCowboy

12

Jeśli użyjesz pełnej wersji składni, twój kod będzie pełny. Oto alternatywa:

List<Tag> result = 
    db.Tags 
    .GroupBy(t => t.Tag) 
    .Select(g => new {Tag = g.Key, Frequency = g.Count()}) 
    .OrderByDescending(t => t.Frequency) 
    .Take(25) 
    .ToList() 
    .Select(t => new Tag(){Tag = t.Tag, Frequency = t.Frequency}) 
    .ToList(); 
+0

Tam, poprawiłem wiele błędów. Skończyłem edycję, lol –

3

myślę, że jesteś również niesprawiedliwe, że zapytanie SQL nie zrobić to samo, co zapytania LINQ - nie zwraca top 25.

+0

Bez wątpienia jest to najtrudniejsza część SQL i jest całkowicie pomijana. – tster