使用Linq将数据表投影到新结构中

使用Linq将数据表投影到新结构中,linq,Linq,我有一个DataTable,我想将其转换为一种新格式(以下是附加到gridview时的结果): 任何指导都将不胜感激 问候, 克里斯你不会在这里做任何按摩;) 数据表的结构将比网格代码更有用,但要从数据表中获得所需内容,您应该这样做 var result = myDataTable.AsEnumerable() .GroupBy(m => m.Field<string>("ProductCategory")) .Selec

我有一个DataTable,我想将其转换为一种新格式(以下是附加到gridview时的结果):

任何指导都将不胜感激

问候,


克里斯

你不会在这里做任何按摩;)

数据表的结构将比网格代码更有用,但要从数据表中获得所需内容,您应该这样做

var result = myDataTable.AsEnumerable()
              .GroupBy(m => m.Field<string>("ProductCategory"))
              .Select(g => new {
                  productCategory = g.Key,
                  sumActual = g.Sum(x => x.Field<decimal>("Actual")),
                  sumTarget = g.Sum(x => x.Field<decimal>("Target"))
               });
var result=myDataTable.AsEnumerable()
.GroupBy(m=>m.Field(“产品类别”))
.选择(g=>new{
productCategory=g.键,
sumActual=g.Sum(x=>x.Field(“实际”),
sumTarget=g.Sum(x=>x.Field(“目标”))
});

Oi,我原以为这会比预期的更难,但最终变得更容易,我重写了这篇文章。您可以在行上执行分组,但只需查询每个组中的行即可获得ProductCategory

首先,您将按主键分组,在本例中,我认为这是
列。因此:

myDataTable.AsEnumerable()
    .GroupBy(m => m.Field<string>("Line"))
编辑:好的,现在我明白你的意思了。我最初的想法是正确的,因为您将每个原始组(基于行)分组为进一步的组。真的没有一个简单的方法,而且选择也不漂亮。事实上,您必须对每个组进行分组,但是为了对组进行分组,您必须查询组中的单个实体,然后根据另外两个实体进行聚合(这使得在这里很难使用LINQ)

myDataTable.AsEnumerable()
.GroupBy(m=>m.Field(“行”))
.选择(g=>new
{
ProductCategory=g.Where(r=>r.Field(“属性”)==“ProductCategory”)
.Select(r=>r.Field(“值”))
.FirstOrDefault()??“无类别”,
实际值=g.Where(r=>r.Field(“属性”)==“实际值”)
.选择(r=>
{ 
十进制d=0m;
十进制.锥巴色(r.字段(“值”),输出d);
返回d;
}
.FirstOrDefault(),
Target=g.Where(r=>r.Field(“属性”)==“Target”)
.选择(r=>
{ 
十进制d=0m;
十进制.锥巴色(r.字段(“值”),输出d);
返回d;
}
.FirstOrDefault()
})
.GroupBy(n=>n.ProductCategory)
.选择(g=>new
{
ProductCategory=g.键,
SumActual=g.Sum(x=>x.Actual),
SumTarget=g.Sum(x=>x.Target)
})
同样,也不是很漂亮……特别是因为“Value”列是string,所以必须解析它们才能得到有意义的值(在本例中,求和一个数字)。这里的前提是将所有记录分组为“块”,然后将这些块组合成单个匿名对象。因此,每个匿名对象表示特定行的所有datarow属性/值对。然后,您只需根据所需的键(本例中为ProductCategory)进行分组,并执行所需的聚合


另外,我实际上会使用PIVOT在数据库端执行此查询。可能需要更多的设置,但您会让设计用于执行这种类型的数据处理/聚合的系统完成它可以处理的工作,并为更重要的事情保留前端CPU周期。

哇,您太快了:)我在g键下遇到一个错误:“char”不包含“Key”的定义@ChrisHardie能否显示数据表的结构?@ChrisHardie:缺少一些
。更正。但是仍然不能确定您的数据表结构。嗨,拉斐尔,我不确定如何更好地演示数据表的结构,而不是通过原始问题中的标记。列为“行”、“开始时间”、“结束时间”、“属性”和“值”。当我运行LINQ查询时,我得到“列‘ProductCategory’不属于表。”“ProductCategory”实际上是某些记录中“Attribute”列的值,而不是列本身,这就是为什么我很难按它进行分组的原因。@ChrisHardie,但您谈论的是DataTable,它是一个c#类。。。那个数据表存在吗?需要明确的是,GridView中数据的来源是什么?问题是“ProductCategory”不是DataTable的字段。只有“行”、“开始时间”、“结束时间”、“属性”和“值”是有效字段。“ProductCategory”是属性字段的可能值。这里的复杂性在于我不希望按列分组,但我需要以这样一种方式显示某些字段值,以便我可以按这些字段值分组。我想我可能需要创建一个占位符集合,我可以将值放入其中,然后查询出来。我的错是,应该按“行”分组,而不是按“ProductCategory”分组。这是我在上面的描述中写的,但我想我的复印/面食工作失败了。啊,我明白了。但是“实际”和“目标”也不是原始数据表中的列,它们也是“属性”列的可能值:)啊,我明白了。好吧,给我一点时间来思考一下。
var result = myDataTable.AsEnumerable()
              .GroupBy(m => m.Field<string>("ProductCategory"))
              .Select(g => new {
                  productCategory = g.Key,
                  sumActual = g.Sum(x => x.Field<decimal>("Actual")),
                  sumTarget = g.Sum(x => x.Field<decimal>("Target"))
               });
myDataTable.AsEnumerable()
    .GroupBy(m => m.Field<string>("Line"))
    ...
    .Select(g => new 
        { 
            ProductCategory = g.Where(r => r.Field<string>("Attribute") == "ProductCategory")
                        .Select(r => r.Field<string>("Value"))
                        .FirstOrDefault() ?? "No Category",
            SumActual = g.Sum(x => x.Field<decimal>("Actual")),
            SumTarget = g.Sum(x => x.Field<decimal>("Target"))
        })
myDataTable.AsEnumerable()
    .GroupBy(m => m.Field<string>("Line"))
    .Select(g => new
        {
            ProductCategory = g.Where(r => r.Field<string>("Attribute") == "ProductCategory")
                        .Select(r => r.Field<string>("Value"))
                        .FirstOrDefault() ?? "No Category",
            Actual = g.Where(r => r.Field<string>("Attribute") == "Actual")
                        .Select(r => 
                            { 
                                decimal d = 0m; 
                                Decimal.TryParse(r.Field<string>("Value"), out d);
                                return d;
                            }
                        .FirstOrDefault(),
            Target = g.Where(r => r.Field<string>("Attribute") == "Target")
                        .Select(r => 
                            { 
                                decimal d = 0m; 
                                Decimal.TryParse(r.Field<string>("Value"), out d);
                                return d;
                            }
                        .FirstOrDefault()
        })
    .GroupBy(n => n.ProductCategory)
    .Select(g => new
        {
            ProductCategory = g.Key,
            SumActual = g.Sum(x => x.Actual),
            SumTarget = g.Sum(x => x.Target)
        })