如何在一个LINQ中获得两个不同的聚合?

时间:2011-05-10 13:28:13

标签: c# .net linq group-by

我有一个这个对象的列表:

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

为了准备在仪表板上显示图表,我试图将此列表压缩到此对象的另一个列表中:

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

最终结果如下所示:

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

我很难想出一个可以达到预期最终结果的LINQ语句。这句话非常接近:

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

显而易见的问题是“Purchased = g.Count()”行,因为它只是重复了试验结果。我想计算BillingStartDate.HasValue为真的对象。

有没有办法重构LINQ以使其工作?

编辑:我更喜欢流利的语法风格,但我无法让上述工作。任何变化的答案都会很棒。

2 个答案:

答案 0 :(得分:3)

您需要将条件传递给Count方法。

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

答案 1 :(得分:2)

所以SLaks有正确的解决方案。这里用流利语法编写:

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