2015-04-01 34 views
0

我试图做的事情相对简单。我想用linq来计算组上的某个聚合函数,然后将结果放回到相同格式的数据表中。我做了大量的研究,并认为我应该使用System.Data.DataSetExtensions并将其复制到数据表函数中。这里是我的随机数据表:在数据表上使用linq并将结果放回到数据表格中,格式相同

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在前面我得到的错误是我无法将anonymys类型转换为数据行。但如果我把选择新的datarow我得到一个错误,字段是未知的...

我该如何继续请?

回答

1

这也适用于:

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(这需要一个参考)

2

你有多种选择,首先是use reflection to create一个DataTable基于IEnumerable<T>和其他选项是通过枚举您的查询像来填充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<DataRow>中。您无法在select中指定DataRow,因为它无法直接访问。

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

+0

感谢。我只是把它排序,将我的方式添加到问题 – nik 2015-04-01 14:27:30

+0

@nik,不要添加/编辑它的问题,而是添加一个单独的* self *答案。这对未来的访问者应该有所帮助。 – Habib 2015-04-01 14:28:09

相关问题