2

我们必须将一个数据表转换为另一个数据表,这主要涉及将源数据表转换为不同的格式。按顺序考虑,我将其实现如下:

DataTable riskTable;
this.InitializeRmmRiskTable(out riskTable); // Initializes the columns

var calculatedRisk = (from DataRow tradeRow in tradeTableToFilter.Rows
                  where tradeRow["TradeID"] != null
                  select new
                          {
                              ROW_ID = 0,
                              TCN = tradeRow["TradeID"].ToString(),                               
                              CCY = tradeRow["CURRENCY"],                                 
                              USD_VALUE = calculator.Invoke(tradeRow) // configured delegate that will fetch the value
                          }).Distinct();

foreach (var rowData in calculatedRisk)
{
    DataRow rowToAdd = riskTable.NewRow();

    rowToAdd["ROW_ID"] = rowData.ROW_ID;
    rowToAdd["TCN"] = rowData.TCN;
    rowToAdd["CCY"] = rowData.CCY;
    rowToAdd["USD_VALUE"] = rowData.USD_VALUE;

    riskTable.Rows.Add(rowToAdd);
}
return riskTable;

有什么建议可以在内存占用和执行周期方面进行优化吗?

4

3 回答 3

2

您可以很容易地删除很多列查找:

object[] values = new object[4];
foreach (var rowData in calculatedRisk)
{
    values[0] = rowData.ROW_ID;
    values[1] = rowData.TCN;
    values[2] = rowData.CCY;
    values[3] = rowData.USD_VALUE;

    riskTable.Rows.Add(values);
}

这假设您知道列的顺序。否则,DataColumnAPI 是最直接的,因此您可以存储 4DataColumn并在索引器中使用它们。这同样适用于阅读代码,即

var tradeId = tradeTableToFilter.Columns["TradeID"];
var currency = tradeTableToFilter.Columns["CURRENCY"];

然后:

var calculatedRisk = (from DataRow tradeRow in tradeTableToFilter.Rows
    let tradeIdVal = tradeRow[tradeId]
    where tradeIdVal != null
    select new {
        ROW_ID = 0,
        TCN = tradeIdVal.ToString(),                               
        CCY = tradeRow[currency],                                 
        USD_VALUE = calculator.Invoke(tradeRow)
    }).Distinct();

等等

的使用Distinct确实意味着所有对象将再次缓冲在内存中;如果你知道你需要这个,很好,但在很多情况下,这可能是多余的。

于 2012-10-30T10:14:31.867 回答
2

一些无需更改代码的提示:

使用索引而不是字符串 id 名称,所以而不是

rowToAdd["ROW_ID"] = rowData.ROW_ID;

我会建议

rowToAdd[0] = rowData.ROW_ID;

另一个技巧,不是DataRow rowToAdd为每个元素创建对象,而是将对象的声明放在迭代之外。

此外,不要使用 foreach,而是使用 for。

此外

var calculatedRisk = (from DataRow tradeRow in tradeTableToFilter.Rows
              where tradeRow["TradeID"] != null
              select
                  new
                      {
                          ROW_ID = 0,
                          TCN = tradeRow["TradeID"].ToString(),                               
                          CCY = tradeRow["CURRENCY"],                                 
                          USD_VALUE = calculator.Invoke(tradeRow) // configured delegate that will fetch the value
                      }).Distinct();

我会一直改这句话,不要使用这样的怪物来声明一个对象,我建议小步进行,或者如果您可以直接访问数据,请使用sql语句过滤并获取数据。

我会使用确切类型的数据,而不是通用的var.

更复杂的更改需要更多地了解代码......

于 2012-10-30T10:19:05.217 回答
1

由于(评论)您提到您愿意更改返回类型的选项,我会声明如下:

public class TradeRisk {
    public int Id {get;set;}
    public string TCN {get;set;} // expand name to be meaningful
    public string Currency {get;set;}
    public decimal UsdValue {get;set;}
}

并将方法更改为 return List<TradeRisk>。我们可以应用与DataColumn我之前的答案相同的技巧,但更改结果 - 注意要保持结果相同,我们需要保留Distinct等。

var tradeId = tradeTableToFilter.Columns["TradeID"];
var currency = tradeTableToFilter.Columns["CURRENCY"];

var calculatedRisk = (from DataRow tradeRow in tradeTableToFilter.Rows
    let tradeIdVal = tradeRow[tradeId]
    where tradeIdVal != null
    select new {
        Id = 0,
        TCN = tradeIdVal.ToString(),                               
        Currency = tradeRow[currency],                                 
        UsdValue = calculator.Invoke(tradeRow)
    }).Distinct();

return (from row in calculatedRisk 
        select new TradeRisk {
            Id = row.Id, TCN = row.TCN,
            Currency = row.Currency,
            UsdValue = row.UsdValue
        }).ToList();

这避免了所有的DataTable开销。如果我们真的想要,我们也可以实现TradeRisk : IEquatable<TradeRisk>,然后就这样做:

return (
    from DataRow tradeRow in tradeTableToFilter.Rows
    let tradeIdVal = tradeRow[tradeId]
    where tradeIdVal != null
    select new TradeRisk {
        Id = 0,
        TCN = tradeIdVal.ToString(),                               
        Currency = tradeRow[currency],                                 
        UsdValue = calculator.Invoke(tradeRow)
    }).Distinct().ToList();
于 2012-10-30T10:35:22.117 回答