¿Cómo puedo obtener dos agregados diferentes en un solo LINQ?

Tengo una lista de este objeto:

public class Customer
{
    public int Id { get; set; }
    public string EmailAddress { get; set; }
    public DateTime ServiceStartDate { get; set; }
    public DateTime? BillingStartDate { get; set; }
    public string Status { get; set; }
}

En preparación para hacer un gráfico que se muestra en un tablero, estoy tratando de condensar esta lista en otra lista de este objeto:

public class DashboardCustomerConversions
{
    public string Month { get; set; }
    public int Trials { get; set; }
    public int Purchased { get; set; }
}

Donde el resultado final se parece a:

Month       Trials   Purchases
---------   ------   ---------
Dec 2010    390      250
Jan 2011    345      190
Feb 2011    576      340

Me está costando encontrar una declaración LINQ que pueda lograr el resultado final deseado. Esta afirmación está muy cerca:

var list = from b in results
           group b by new { b.ServiceStartDate.Year, b.ServiceStartDate.Month } into g
           select new Test
                      {
                          Month = string.Format("{0} {1}", CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(g.Key.Month), g.Key.Year),
                          Trials = g.Count(),
                          Purchased = g.Count()
                      };

El problema obvio es la línea "Purchased = g.Count ()", ya que simplemente repite el resultado de las pruebas. Me gustaría contar los objetos donde BillingStartDate.HasValue es verdadero.

¿Hay alguna forma de reestructurar el LINQ para que esto funcione?

Editar: Preferiría un estilo de sintaxis fluido, pero no pude hacer que lo anterior funcionara. Responder en cualquier variación sería genial.

preguntado el 10 de mayo de 11 a las 13:05

2 Respuestas

Necesita transmitir una condición al Count método.

Purchased = g.Count(q => q.BillingStartDate.HasValue)

contestado el 10 de mayo de 11 a las 17:05

¡Argh! Yo estaba tan cerca. Seguí intentando pasar "b" o "g" sabiendo que estaba mal, pero no podía encontrar algo mejor. Todavía apesto en lambdas. Gracias. - Judo de vela

Entonces SLaks tenía la solución adecuada. Aquí está escrito en sintaxis fluida:

listOfCustomer.GroupBy(c => new { c.ServiceStartDate.Year, c.ServiceStartDate.Month })
              .Select(group => new DashboardCustomerConversions()
                                {
                                    Month = string.Format("{0} {1}", CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(group.Key.Month), group.Key.Year),
                                    Trials = group.Count(),
                                    Purchased = group.Count(c => c.BillingStartDate.HasValue)
                                });

contestado el 10 de mayo de 11 a las 17:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.