我们不得不将数据表转换为另一个数据表,其中主要是将源数据表转换为不同的格式。 按顺序思考它,我已经实现了如下:
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;
有关内存占用和执行周期方面的优化建议吗?
答案 0 :(得分: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);
}
这假设您知道列的顺序。否则,DataColumn
API是最直接的,因此您可以存储4 DataColumn
并在索引器中使用它们。这同样适用于读取代码,即
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
意味着所有对象将再次缓存在内存中;如果你知道你需要这个,那很好,但在很多情况下这可能是多余的。
答案 1 :(得分:2)
一些提示而不改变代码mutch:
使用索引intead字符串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
。
更复杂的变化需要更多地了解代码...
答案 2 :(得分: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;}
}
并将方法更改为返回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();