在数据表上使用 linq 并将结果以相同的格式放回数据表
using linq on datatable and putting result back into datatable with same format
我想做的事情比较简单。我想使用 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 放在前面,我就会收到无法将 anonymys 类型转换为数据行的错误。但是,如果我放入 select 新数据行,我会收到一个字段未知的错误...
请问我该如何进行?
您有多种选择,首先是 use reflection to create 基于 IEnumerable<T>
的 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<DataRow>
中。您不能在 select
中指定 DataRow
,因为它无法直接访问。
您可能还会看到:How to: Implement CopyToDataTable Where the Generic Type T Is Not a DataRow
这也有效:
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(需要参考)
我想做的事情比较简单。我想使用 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 放在前面,我就会收到无法将 anonymys 类型转换为数据行的错误。但是,如果我放入 select 新数据行,我会收到一个字段未知的错误...
请问我该如何进行?
您有多种选择,首先是 use reflection to create 基于 IEnumerable<T>
的 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<DataRow>
中。您不能在 select
中指定 DataRow
,因为它无法直接访问。
您可能还会看到:How to: Implement CopyToDataTable Where the Generic Type T Is Not a DataRow
这也有效:
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(需要参考)