30 votes

GROUP BY "le plus populaire" dans LINQ?

En supposant une table de balises comme le stackoverflow question tags:

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

Quel est le moyen le plus efficace pour obtenir les 25 plus utilisé balises à l'aide de LINQ? Dans SQL, un simple GROUPE de PAR la volonté de faire:

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

J'ai écrit certains de LINQ qui fonctionne:

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

Comme, vraiment? N'est-ce pas mega-verbose? Le plus triste, c'est que je fais cela pour sauver un grand nombre de requêtes, comme sur mon Tag objets contiennent déjà une Fréquence de propriété qui serait autrement nécessaire de vérifier de retour avec la base de données pour chaque Balise si j'ai effectivement utilisé la propriété.

J'ai donc ensuite d'analyser ces types anonymes de retour dans la Balise objets:

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

Je suis une LINQ newbie, et cela ne semble pas juste. Merci de me montrer comment il est vraiment fait.

25voto

GalacticCowboy Points 8185

Si vous voulez des objets Tag, pourquoi ne pas les créer directement à partir de votre requête 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);
 

12voto

David B Points 53123

Si vous utilisez la forme détaillée de la syntaxe, votre code sera détaillé. Voici une alternative:

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

10voto

James Curran Points 55356

Je suis sûr que vous avez raison. Et, le SQL que LINQ génère et enverra à votre base de données ressemblera exactement au SQL avec lequel vous avez commencé, donc pendant que vous faites un peu plus de frappe, votre base de données ne fait plus de travail.

3voto

NetMage Points 163

Je pense que vous êtes également injuste dans la mesure où votre requête SQL ne fait pas la même chose que votre requête LINQ - elle ne renvoie pas le top 25.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X