2008-10-30 4 views
30

Предполагая таблицу тегов, как StackOverflow вопрос теги:"Самый популярный" GROUP BY in LINQ?

TagID (BIGINT), QuestionID (BIGINT), Tag (VARCHAR)

Что является наиболее эффективным способом, чтобы получить 25 наиболее используя теги LINQ? В SQL простой GROUP BY будет делать:

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

Я написал некоторые LINQ, который работает:

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

Мол, на самом деле? Разве это не мега-многословие? Печально то, что я делаю это, чтобы сохранить огромное количество запросов, так как мои объекты Tag уже содержат свойство Frequency, которое в противном случае потребовалось бы проверить с базой данных для каждого тега, если я действительно использовал свойство.

Так я тогда разобрать эти анонимные типы назад в объекты Tag:

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

Я новичок LINQ, и это не кажется правильным. Пожалуйста, покажите мне, как это делается.

+0

Я считаю, что ваш SQL должен быть `SELECT Tag, COUNT (тег) FROM Tags GROUP BY Tag ORDER BY COUNT (тег) DESC FETCH FIRST 25 ROWS ONLY`, который не делает Linq показаться настолько плохим. – NetMage 2016-10-07 00:17:23

ответ

10

Я уверен, что у вас все в порядке. И SQL, который LINQ генерирует и отправит на ваш db, будет выглядеть так же, как SQL, с которого вы начали, поэтому, пока вы немного набираете текст, ваша база данных больше не работает.

24

Если вы хотите объекты Tag, почему бы не создать их непосредственно из вашего запроса 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! Это то, чего мне не хватало, спасибо! – tags2k 2008-10-30 17:08:29

+0

В дополнение к этому, я получил ошибку «явное построение типа объекта в запросе не допускается». Кажется, вы не можете! – tags2k 2008-10-30 17:51:21

+0

Я подозреваю, что это потому, что Tag - это тип контекста данных - вы можете сделать это с другими типами, но Linq, по-видимому, пытается защитить вас от создания экземпляров тегов, которые не соответствуют элементам контекста данных. – GalacticCowboy 2008-10-30 19:35:06

12

Если вы используете подробную форму синтаксиса, ваш код будет подробным. Вот альтернатива:

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

Я думаю, вы также несправедливо в том, что ваш SQL запрос не делать то же самое, как ваш запрос LINQ - это не возвращает топ 25.