【问题标题】:using linq on datatable and putting result back into datatable with same format在数据表上使用 linq 并将结果以相同格式放回数据表中
【发布时间】:2015-04-01 14:07:26
【问题描述】:

我想做的事情相对简单。我想使用 linq 在组上计算一些聚合函数,然后将结果放回相同格式的数据表中。我做了很多研究,认为我应该使用 System.Data.DataSetExtensions 并复制到数据表功能。这是我的随机数据表:

DataTable ADataTable = new DataTable("ADataTable");

        // Fake table data
        ADataTable.Columns.Add("PLANT", typeof(int));
        ADataTable.Columns.Add("PDCATYPE_NAME", typeof(int));
        ADataTable.Columns.Add("Month", typeof(int));
        ADataTable.Columns.Add("Year", typeof(int));
        ADataTable.Columns.Add("STATUS_NAME_REPORT", typeof(string));
        ADataTable.Columns.Add("SAVINGS_PER_MONTH", typeof(double));

        for (int i = 0; i < 15; i++)
        {
            for (int j = 1; j < 5; j++)
            {
                DataRow row = ADataTable.NewRow();

                row["PLANT"] = j;
                row["PDCATYPE_NAME"] = j;
                row["Month"] = DateTime.Now.Month;
                row["Year"] = DateTime.Now.Year;
                row["STATUS_NAME_REPORT"] = "Report";
                row["SAVINGS_PER_MONTH"] = j*i;

                ADataTable.Rows.Add(row);
            }
        }

现在我将克隆这种格式并通过 linq 对其进行简单的求和:

 DataTable newtable = ADataTable.Clone();

        // The actual query
        IEnumerable<DataRow> query = (from rows in ADataTable.AsEnumerable()
                                      group rows by new
                                      {
                                          PLANT = rows.Field<int>("PLANT"),
                                          PDCATYPE_NAME = rows.Field<int>("PDCATYPE_NAME"),
                                          Month = rows.Field<int>("Month"),
                                          Year = rows.Field<int>("Year"),
                                          STATUS_NAME_REPORT = rows.Field<string>("STATUS_NAME_REPORT")
                                      } into g

                                      select new  
                                      {
                                           g.Key.PLANT,
                                           g.Key.PDCATYPE_NAME,
                                          g.Key.Month,
                                          g.Key.Year,
                                          g.Key.STATUS_NAME_REPORT,
                                          sum = g.Sum(savings => savings.Field<double>("SAVINGS_PER_MONTH")),
                                      });

        newtable = query.CopyToDataTable<DataRow>();

LINQ 工作正常,但只要我将 IEnumarable DataRow 放在前面,我就会收到无法将匿名类型转换为数据行的错误。但是,如果我把 select new datarow 我得到一个字段未知的错误......

请问我该怎么做?

【问题讨论】:

    标签: c# linq datatable


    【解决方案1】:

    您有多种选择,首先是基于IEnumerable&lt;T&gt;use reflection to create DataTable,其他选项是通过枚举您的查询来填充您的DataTable

    var query = ADataTable.AsEnumerable()
        .GroupBy(row => new
        {
            PLANT = row.Field<int>("PLANT"),
            PDCATYPE_NAME = row.Field<int>("PDCATYPE_NAME"),
            Month = row.Field<int>("Month"),
            Year = row.Field<int>("Year"),
            STATUS_NAME_REPORT = row.Field<string>("STATUS_NAME_REPORT")
        });
    
    foreach (var g in query)
    {
        newtable.LoadDataRow(new object[]
        {
                     g.Key.PLANT,
                     g.Key.PDCATYPE_NAME,
                     g.Key.Month,
                     g.Key.Year,
                     g.Key.STATUS_NAME_REPORT,
                    g.Sum(savings => savings.Field<double>("SAVINGS_PER_MONTH"))
        }, LoadOption.OverwriteChanges);
    }
    

    代码中的错误是因为使用select new 选择了一个匿名类型,然后尝试将其存储在IEnumerable&lt;DataRow&gt; 中。您不能在 select 中指定 DataRow,因为它不能直接访问。

    您可能还会看到:How to: Implement CopyToDataTable Where the Generic Type T Is Not a DataRow

    【讨论】:

    • 谢谢。我也刚刚排序,会添加我的问题的方式
    • @nik,不要在问题中添加/编辑它,而是添加一个单独的 self 答案。它应该对未来的访问者有所帮助。
    【解决方案2】:

    这也有效:

    newtable2 = ADataTable.AsEnumerable().GroupBy(a => new
    {
        PLANT = a.Field<int>("PLANT"),
        PDCATYPE_NAME = a.Field<int>("PDCATYPE_NAME"),
        Month = a.Field<int>("Month"),
        Year = a.Field<int>("Year"),
        STATUS_NAME_REPORT = a.Field<string>("STATUS_NAME_REPORT")
    }).Select(g =>
    {
        var row = newtable2.NewRow();
        row.ItemArray = new object[]
                {
                    g.Key.PLANT, 
                    g.Key.PDCATYPE_NAME,
                    g.Key.Month,
                    g.Key.Year,
                    g.Key.STATUS_NAME_REPORT,
                    g.Sum(r => r.Field<double>("SAVINGS_PER_MONTH"))
                };
        return row;
    }).CopyToDataTable();
    

    使用 System.Data.DataSetExtensions(需要参考)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      • 2012-09-22
      • 2012-03-04
      • 2017-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多