Question
J'expérimente avec Linq et j'ai du mal à comprendre le regroupement.J'ai suivi plusieurs tutoriels mais, pour une raison quelconque, je n'arrive pas à comprendre.
À titre d'exemple, disons que j'ai un tableau (SiteStats) avec plusieurs identifiants de sites Web qui stocke le nombre de visiteurs par type qui ont accédé à chaque site au total et au cours des 30 derniers jours.
╔════════╦═════════════╦════════╦══════╗
║ SiteId ║ VisitorType ║ Last30 ║ Total║
╠════════╬═════════════╬════════╬══════╣
║ 1 ║ 1 ║ 10 ║ 100 ║
║ 1 ║ 2 ║ 40 ║ 140 ║
║ 2 ║ 1 ║ 20 ║ 180 ║
╚════════╩═════════════╩════════╩══════╝
En SQL, je peux facilement obtenir les décomptes pour SiteID 1 avec ce qui suit :
SELECT SiteId,
SUM(Last30) AS Last30Sum
FROM Sites
WHERE SiteId = 1
GROUP BY SiteId
et devrait avoir une ligne comme...
╔════════╦════════════╗
║ SiteId ║ Last30Total║
╠════════╬════════════╣
║ 1 ║ 50 ║
╚════════╩════════════╝
Cependant, je ne sais pas comment obtenir ce résultat en utilisant Linq.J'ai essayé:
var statsRecord = from ss in db.SiteStats
where ss.SiteId == siteId
group ss by ss.SiteId into ss
select ss;
mais je ne parviens pas à récupérer le total avec quelque chose comme statsRecord.Last30
Quelqu'un peut-il me faire savoir où je me trompe ?Toute aide est appréciée.
La solution
En fait, même si le code de Thomas fonctionnera, il est plus succint d'utiliser une expression lambda :
var totals =
from s in sites
group s by s.SiteID into grouped
select new
{
SiteID = grouped.Key,
Last30Sum = grouped.Sum( s => s.Last30 )
};
qui utilise la méthode d'extension Sum sans avoir besoin d'une opération LINQ imbriquée.
selon les exemples LINQ 101 - http://msdn.microsoft.com/en-us/vcsharp/aa336747.aspx#sumGrouped
Autres conseils
Le moyen le plus simple pour moi d'illustrer consiste à utiliser des objets en mémoire pour que ce qui se passe soit clair.LINQ to SQL devrait être capable de prendre cette même requête LINQ et de la traduire en SQL approprié.
public class Site
{
static void Main()
{
List<Site> sites = new List<Site>()
{
new Site() { SiteID = 1, VisitorType = 1, Last30 = 10, Total = 100, },
new Site() { SiteID = 1, VisitorType = 2, Last30 = 40, Total = 140, },
new Site() { SiteID = 2, VisitorType = 1, Last30 = 20, Total = 180, },
};
var totals =
from s in sites
group s by s.SiteID into grouped
select new
{
SiteID = grouped.Key,
Last30Sum =
(from value in grouped
select value.Last30).Sum(),
};
foreach (var total in totals)
{
Console.WriteLine("Site: {0}, Last30Sum: {1}", total.SiteID, total.Last30Sum);
}
}
public int SiteID { get; set; }
public int VisitorType { get; set; }
public int Last30 { get; set; }
public int Total { get; set; }
}