首页 > 解决方案 > 使用动态 GroupBy 子句的 Linq 实现

问题描述

在下面的 Linq 语句中,我在尝试获取数据表字段(如“ID”)并将其分配给行 [“ID”] 时遇到“选择”错误。

//row["ID"] =  g.Field<decimal>("ID");

错误信息:

System.Linq.IGrouping<string,System.Data.DataRow>不包含“字段”的定义

var x = groupedDataRow
    .AsEnumerable()
    .Select(g =>
    {
        var row = dataTable.NewRow();
        //row["ID"] =  g.Field<decimal>("ID");
        row["AMT"] = g.Sum(r => r.Field<decimal>("AMT"));
        row["PERCENTAGE"] = g.Sum(r => r.Field<decimal>("PERCENTAGE"));
        return row;
    }).CopyToDataTable();

如何检索像“ID”这样的数据表字段,以便在 Select 语句中将其分配给 row[“ID”]?

Linq 示例

 public class Program
 {
    static StringBuilder stringBuilder = new StringBuilder();
    public static String GroupData(DataRow dataRow)
    {
        String[] columnNames = new[] {"ID","COL1", "COL2"};
        stringBuilder.Remove(0, stringBuilder.Length);
        foreach (String column in columnNames)
        {
            stringBuilder.Append(dataRow[column].ToString());
        }
        return stringBuilder.ToString();
    }

    public static void Main()
    {
         DataTable dataTable = new DataTable("MyTable");

        DataColumn dc2 = dataTable.Columns.Add("ID", typeof(decimal));  
        dataTable.Columns.Add("AMT", typeof(decimal));  
        dataTable.Columns.Add("PERCENTAGE", typeof(decimal));  
        dataTable.Columns.Add("COL1", typeof(String));  
         dataTable.Columns.Add("COL2", typeof(String));

        dataTable.Rows.Add(000, 400,100,"sss","vvv");  
        dataTable.Rows.Add(888, 400, 100,"qqq","fff");  
        dataTable.Rows.Add(000, 300, 100,"eee","aaa");  
        dataTable.Rows.Add(000, 300, 100,"eee","aaa");  
        dataTable.Rows.Add(000,400,100,"sss","vvv");  




         EnumerableDataRowList<DataRow> enumerableRowCollection = new EnumerableDataRowList<DataRow>(dataTable.Rows);

        Func<DataRow, String> groupingFunction = GroupData;
        var groupedDataRow = enumerableRowCollection.GroupBy(groupingFunction);

        var x = groupedDataRow.AsEnumerable()
                .Select(g =>
                        {
                            var row = dataTable.NewRow();
                            //row["ID"] =  g.Field<decimal>("ID");
                            row["AMT"] = g.Sum(r => r.Field<decimal>("AMT"));
                            row["PERCENTAGE"] = g.Sum(r => r.Field<decimal>("PERCENTAGE"));
                            return row;
                        }).CopyToDataTable();


        foreach(DataRow row in x.Rows)
        {
            Console.WriteLine(row["ID"].ToString() + " " + row["COL1"].ToString() + " " + row["COL2"].ToString() + " " + row["AMT"].ToString() + " " + row["PERCENTAGE"].ToString()) ;
        }
    }


class EnumerableDataRowList<T> : IEnumerable<T>, IEnumerable
{
    IEnumerable dataRows;
    internal EnumerableDataRowList(IEnumerable items)
    {
        dataRows = items;
    }
    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        foreach (T dataRow in dataRows)
            yield return dataRow;
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        IEnumerable<T> iEnumerable = this;
        return iEnumerable.GetEnumerator();
    }
}

标签: linq

解决方案


这是因为gIGrouping没有Field成员。

您可以尝试以下方法:

  var x = groupedDataRow.AsEnumerable()
          .Select(g =>
          {
            var row = dataTable.NewRow();
            row["ID"] = g.Select(r => r.Field<decimal>("ID")).FirstOrDefault();
            row["AMT"] = g.Sum(r => r.Field<decimal>("AMT"));
            row["PERCENTAGE"] = g.Sum(r => r.Field<decimal>("PERCENTAGE"));
            return row;
          }).CopyToDataTable();

或者

  var x = groupedDataRow.AsEnumerable()
          .Select(g =>
          {
            var row = dataTable.NewRow();
            row["ID"] = g.First().Field<decimal>("ID");
            row["AMT"] = g.Sum(r => r.Field<decimal>("AMT"));
            row["PERCENTAGE"] = g.Sum(r => r.Field<decimal>("PERCENTAGE"));
            return row;
          }).CopyToDataTable();

它应该是安全的,g.First()因为一个组只有在它包含任何项目时才是一个组。


推荐阅读