Pergunta

Estou experimentando o Linq e estou tendo problemas para descobrir o agrupamento.Já passei por vários tutoriais, mas por algum motivo não consigo descobrir isso.

Por exemplo, digamos que eu tenha uma tabela (SiteStats) com vários IDs de sites que armazena uma contagem de quantos visitantes por tipo acessaram cada site no total e nos últimos 30 dias.

╔════════╦═════════════╦════════╦══════╗
║ SiteId ║ VisitorType ║ Last30 ║ Total║
╠════════╬═════════════╬════════╬══════╣
║      1 ║           1 ║     10 ║  100 ║
║      1 ║           2 ║     40 ║  140 ║
║      2 ║           1 ║     20 ║  180 ║
╚════════╩═════════════╩════════╩══════╝

No SQL, posso obter facilmente as contagens do SiteID 1 com o seguinte:

SELECT SiteId,  
       SUM(Last30) AS Last30Sum  
FROM Sites  
WHERE SiteId = 1  
GROUP BY SiteId

e deve obter uma linha como ...

╔════════╦════════════╗
║ SiteId ║ Last30Total║
╠════════╬════════════╣
║      1 ║         50 ║
╚════════╩════════════╝

No entanto, não tenho certeza de como obter esse resultado usando o Linq.Eu tentei:

var statsRecord = from ss in db.SiteStats  
    where ss.SiteId == siteId  
    group ss by ss.SiteId into ss  
    select ss;

mas não consigo recuperar o total com algo como statsRecord.Last30

Alguém pode me informar onde estou errando?Qualquer ajuda é apreciada.

Foi útil?

Solução

Na verdade, embora o código de Thomas funcione, é mais sucinto usar uma expressão 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 )
};

que usa o método de extensão Sum sem a necessidade de uma operação LINQ aninhada.

conforme os exemplos do LINQ 101 - http://msdn.microsoft.com/en-us/vcsharp/aa336747.aspx#sumGrouped

Outras dicas

A maneira mais fácil de ilustrar é usar objetos na memória para que fique claro o que está acontecendo.O LINQ to SQL deve ser capaz de pegar a mesma consulta LINQ e traduzi-la em SQL apropriado.

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; }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top