动态添加属性到Linq的GroupBy结果

时间:2018-02-07 09:16:45

标签: c# asp.net .net linq razor

我有两个班级,CustomerKPI

public class Customer : BaseModel
{
    public String Code { get; set; }
    ...
    public List<KPI> KPIs { get; set; }
}

public class KPI : BaseModel
{
    public String Name { get; set; }
    public int PersonalValue { get; set; }
    public int RegionalValue { get; set; }
    public int NationalValue { get; set; }
    public String Group { get; set; }
}

我需要通过Group属性对KPI进行分组,这样如果我的数据如下所示:

+---------------------------------+
| Name PValue RValue NValue Group |
+---------------------------------+
| Low    100    600    300    Car  |
| High   900    400    700    Car  |
| Low    200    300    500   Truck |
| High   800    700    500   Truck |
+---------------------------------+

在对项目进行分组后,我需要一些额外的属性:

Names: 'Low, High' PValuePercentages: '10, 90' RValuePercentages: '60, 40' NValuePercentages: '30, 70'

这基本上是逗号分隔的字符串,其中包含来自分组项目的计算值。我需要将它们格式化,以便我可以使用Razor轻松地将它们插入HTML元素。

这正是我目前在Razor中正在做的事情,但是在.cs文件中,以便进行更简单的测试和调试:

foreach (var customer in customerList)
{
    var groups = customer.KPIs.GroupBy(item => item.Group);

    foreach (var group in groups)
    {
        var groupName = group.Key ?? "OTHERS";

        foreach (var kpi in group)
        {
            var kpiName = kpi.Name;
            var personalValue = kpi.PersonalValue;
            var regionalValue = kpi.RegionalValue;
            var nationalValue = kpi.NationalValue;
        }

        if(!String.IsNullOrEmpty(group.Key))
        {
            // This doesn't work yet
            //var acuVal1 = group.AcuVal1;
            //var acuVal2 = group.AcuVal2;
            //var acuVal3 = group.AcuVal3;


            foreach (var kpi in group)
            {
                var kpiName= kpi.Name;   
            }
        }
    }
}

如果我尝试通过Linq查询将组更改为

var groups = customer.KPIs.GroupBy(item => item.Group).
                    Select(item => new
                    {
                        item.Key,
                        item,
                        AcuVal1 = item.Sum(i => i.PersonalValue),
                        AcuVal2 = item.Sum(i => i.RegionalValue),
                        AcuVal3 = item.Sum(i => i.NationalValue)
                    }).ToList();

注意:在这种情况下,Sum()不是我需要的,但出于测试目的,它可以正常运行并保持简单。

执行此操作后,行

foreach (var kpi in grupo)

给出以下错误:

  

foreach语句不能对类型'&lt;的变量进行操作匿名   type:string Key,IGrouping item,int AcuVal1,int   AcuVal2,int AcuVal3&gt;'因为'&lt;匿名类型:string Key,   IGrouping项目,int AcuVal1,int AcuVal2,int AcuVal3&gt;'   不包含'GetEnumerator'

的公共定义

我做错了什么?

1 个答案:

答案 0 :(得分:0)

当您group by进入时,是键值的IGrouping,而只是具有属性和一些聚合属性以及属性的匿名类型的集合。

考虑到所有这些,如果你想迭代一个分组的子集合,你需要迭代一个组的 .item 属性

var groups = from kpi in kpis
            group kpi by kpi.Group into item
            select new
            {
                item.Key,
                item,
                AcuVal1 = item.Sum(i => i.PersonalValue),
                AcuVal2 = item.Sum(i => i.RegionalValue),
                AcuVal3 = item.Sum(i => i.NationalValue)
            };

foreach (var group in groups)
{
    foreach (var kpi in group.item)
    {
        var kpiName = kpi.Name;
    }
}

注意:我非常确定您实际上并不需要嵌套的foreach,并且您应该能够通过结果查询实现所需的结果扩展

var groups = from kpi in kpis
            group kpi by kpi.Group into groupings
            let names = groupings.Select(p => p.Name)
            let pvalues = groupings.Select(p => p.PersonalValue)
            let rvalues = groupings.Select(p => p.RegionalValue)
            let nvalues = groupings.Select(p => p.NationalValue)
            select new
            {
                Key = groupings.Key,
                Names = string.Join(", ", names),
                PValues = string.Join(", ", pvalues),
                RValues = string.Join(", ", rvalues),
                NValues = string.Join(", ", nvalues),
            };

outcome