C# 在多个数据行中创建列集合的干净方法

C# 在多个数据行中创建列集合的干净方法,c#,dataset,C#,Dataset,我有一系列DataRow对象,每个对象都有一组不同的字段。我要做的是创建一个新的DataRow对象,其中包含某些十进制字段的总和。现在,我的代码如下所示: DataRow tally = myTable.NewRow(); foreach (DataRow row in myTable.Rows) { if (row["SomeField"] != DBNull.Value) tally["SomeField"] = (tally["SomeField"] is DBNull

我有一系列DataRow对象,每个对象都有一组不同的字段。我要做的是创建一个新的DataRow对象,其中包含某些十进制字段的总和。现在,我的代码如下所示:

DataRow tally = myTable.NewRow();

foreach (DataRow row in myTable.Rows)
{
   if (row["SomeField"] != DBNull.Value)
      tally["SomeField"] = (tally["SomeField"] is DBNull ? 0 : (Decimal)tally["SomeField"]) + (Decimal)row["SomeField"];

   // ...     
}
我需要对大约20个其他字段执行同样的操作,但我认为由于所有类型转换和空检查,代码非常混乱。是否有办法重构此代码,使其更具可读性


注意:我只想对某些列进行汇总,否则我可能只会在DataRow中的列中循环,而不是重复上面的代码20次。

您可以使用Linq对数据集进行汇总:

如果您想使用LINQ,这里有一个简单的示例

DataTable table = new DataTable();
table.Columns.Add("Desc", typeof(string));
table.Columns.Add("Qty", typeof(decimal));
table.Columns.Add("Price", typeof(decimal));

table.Rows.Add(new object[] { "Product", 1, 2 });
table.Rows.Add(new object[] { "Product", 2, 10 });
table.Rows.Add(new object[] { "Product", 3, null });

var totalQty = table.AsEnumerable().GroupBy(l => l.Field<string>("Desc"))
    .Select(r =>
        new {   Desc = r.Key,
                TotalQty = r.Sum(w => w.Field<decimal?>("Qty")),
                TotalPrice = r.Sum(w => w.Field<decimal?>("Price")),
        });

您可以将计算代码移动到新方法中:

private void Tally(DataRow tally, DataRow row, int index)
{
    if (row[index] != DBNull.Value)
    {
        tally[index] = (tally[index] == DBNull.Value ? 0 : (decimal)tally[index]) + (decimal)row[index];
    }
}
并对要计数的列使用索引数组:

DataRow tally = myTable.NewRow();

int[] indexes = new int[] { 0, 2 };

foreach(DataRow row in myTable.Rows)
{
    foreach(int index in indexes)
    {
        Tally(tally, row, index);
    }
}

您还可以使用DataTable类的Compute方法:。

我有点想避免这种情况,因为我已经在数据集中循环以写出每一行,LINQ表达式将导致我再次遍历数据集,然后获得总数。是的,我实际上正在考虑这种方法(只使用字符串数组,因为我讨厌在列索引中进行硬编码)…这确实让东西不那么难看。这也是我能找到的最干净的方法。我循环使用字符串数组,并称我的“凌乱”每次迭代编写一次代码。我决定不过度考虑使用LINQ,因为我想自己控制循环,而不是执行大量O(n)LINQ调用。
DataRow tally = myTable.NewRow();

int[] indexes = new int[] { 0, 2 };

foreach(DataRow row in myTable.Rows)
{
    foreach(int index in indexes)
    {
        Tally(tally, row, index);
    }
}