c# datatable -有效地从数据表中为每个主记录选择详细记录
本文关键字:记录 选择 datatable 有效地 数据表 | 更新日期: 2023-09-27 18:02:05
我有一个主数据表,其中包含按发票#排序的发票记录。我还有另一个数据表,其中包含所有发票记录的详细信息(行项信息),按发票编号&行项目编号
如何从这两个表中有效地创建发票对象数组?对我来说,它看起来像是创建嵌套的For循环。外部for循环遍历orders表,内部for循环遍历行项表
我将保留一个保存当前发票#的临时标识符,一旦它在嵌套的for循环中找到不同的发票#,它将退出内部循环。
下面是我要做的伪代码
long currentInvoiceNumber=-1;
int CurrentJCounter=0;
for(int i=0;i<MasterTable.Rows.Count;i++)
{
currentInvoiceNumber=MasterTable.Rows[i]["invoiceno"];
Order oOrder = new Order();
for(int j=CurrentJCounter;j<ItemDetailsTable.Row.Count;j++)
{
if(currentInvoiceNumber!=ItemDetailsTable.Rows[j]["invoiceno"])
{
currentJCounter = j;
break;
}
else
{
oOrder.AddItem(ItemDetailsTable.Rows[j]);
}
}
lstOrders.Add(oOrder);
}
我必须提高应用程序的性能,我认为肯定有比这更好的方法。请建议
谢谢,Sveerap
为了改进,您应该用感兴趣的字段排序第二个表,这是内部循环目标表(ItemDetailsTable
)。当然,它会产生负面影响,但可以避免在大于/小于条件下不必要的内部循环。
我不知道是否,如果你使用LINQ对象/数据集,它将自动应用或不
方法A:
您可以使用LINQ确定发票的所有行列表,如:
var invoiceRows = (from r in ItemDetailsTable.Rows where r["invoiceno"].Equals(currentInvoiceNumber) select r);
(请注意,我现在还没有对此进行测试-您可能需要稍微摆弄一下LINQ语句,或者可能必须首先使用类型化数据集)
然后你可以遍历结果:
foreach (var invoiceRow in invoiceRows)
{
oOrder.AddItem(invoiceRow);
}
然而,我不知道这是否会提高性能-它可能在阅读代码时"看起来"更优雅,然而;-)
至于退出内部循环:是否给定ItemDetailsTable行按发票编号"排序"?如果不是,如果发票B的一行位于发票A的两行之间,则可能会丢失发票A的一些行,如
所示。Row 1 for invoice A
Row 2 for invoice A
Row 1 for invoice B
Row 3 for invoice A
Row 2 for invoice B
...
方法B
另一种方法可能如下:声明一个字典,以发票号作为键,如
Dictionary<string, Order> orderList = new ...;
然后,只迭代行:
for (int j = 0; j < ItemDetailsTable.Row.Count; j++)
{
if (!orderList.ContainsKey(ItemDetailsTable.Row[j]["invoiceno"]))
orderList[ItemDetailsTable.Row[j]["invoiceno"]] = new Order();
Order oOrder = orderList[ItemDetailsTable.Row[j]["invoiceno"]];
oOrder.AddItem(ItemDetailsTable.Rows[j]);
}
最后,您可以通过键(发票号)或直接使用字典的值集合访问所有发票。
编辑
作为方法b的注释:
最后,字典可能不包含MasterTable
中的所有发票号码-如果没有发票号码行,则不会添加任何条目。您可以通过在迭代行之前为MasterTable
中的每个发票号添加一个条目来解决这个问题。
此外,字典最终可能包含不在MasterTable
中的发票号。这些不会包含在嵌套循环方法中。通过在迭代行之前在单独的循环中添加发票号,然后修改我的代码示例,这样如果发票号尚未在字典中,则不会在字典中创建新项,您还可以防止这种情况。