加入并更新DataTable

时间:2013-12-19 13:19:04

标签: c# asp.net linq datatable

我有两个Table1和Table2,其值的列如下: 这是两个表: 我想更新Table1中的“PaidAmount”。根据两个表中的“InvoiceNo”列加入。

表1:

 InvoiceNo  Vendor   InvoiceValue  InvoiceDate      PaidAmount 
 ---------  ------   ------------- -----------      ---------- 
    1        AA        15000       01 Dec 2013         0      
    2        BB        20000       10 Dec 2013         0      
    3        CC        10000       18 Dec 2013         0      

表2:

 VoucherNo   Date       InvoiceNo  Amount
 -------   ----------- ----------  ------
   001     01 Nov 2013    1         5000
   002     10 Nov 2013    2         6000
   003     20 Nov 2013    3         7000
   001     02 Nov 2013    1         2000

我想要的数据表应该是这样的:

DesiredTable:

 InvoiceNo  Vendor   InvoiceValue  InvoiceDate      PaidAmount 
 ---------  ------   ------------- -----------      ---------- 
     1        AA        15000       01 Dec 2013        7000      
     2        BB        20000       10 Dec 2013        6000
     3        CC        10000       18 Dec 2013        7000

如何实现这一结果? 我试过下面的一个。

Table1.AsEnumerable().Join(Table2.AsEnumerable(),
                      dt1_Row => dt1_Row.ItemArray[0],
                      dt2_Row => dt2_Row.ItemArray[2],
                      dt1_Row, dt2_Row) => new { dt1_Row, dt2_Row }
                      ).ToList()
                   .ForEach(o => o.dt1_Row.SetField(4, o.dt2_Row.ItemArray[3]));

但它将结果作为

InvoiceNo  Vendor   InvoiceValue  InvoiceDate      PaidAmount 
---------  ------   ------------- -----------      ---------- 
    1        AA        15000       01 Dec 2013        2000      
    2        BB        20000       10 Dec 2013        6000
    3        CC        10000       18 Dec 2013        7000

如何获得我想要的桌子?

3 个答案:

答案 0 :(得分:1)

看起来你正在迭代你的结果和覆盖,而不是添加到其他行的预先存在的结果。你可能想做这样的事情:

Table1.AsEnumerable().Join(Table2.AsEnumerable(),
                      dt1_Row => dt1_Row.ItemArray[0],
                      dt2_Row => dt2_Row.ItemArray[2],
                      dt1_Row, dt2_Row) => new { dt1_Row, dt2_Row }
                      ).ToList()
                   .ForEach(o => o.dt1_Row.SetField(4, o.dt1_Row.ItemArray[4] +  o.dt2_Row.ItemArray[3]));

答案 1 :(得分:1)

您的联接会为您提供多个row1,row2对的列表。
所以你在每一对夫妇中循环,第一次为invoiceNo1,row1.PaidAmount = 5000,然后你的循环继续,第二次,row1.PaidAmount = 2000,所以你的结果。

您想要对row2的Amount值求和,所以在加入之后,您必须按InvoiceValue对数据进行分组,然后执行求和:

foreach(var grp in Table1.AsEnumerable()
      .Join(Table2.AsEnumerable(),
            dt1_Row => dt1_Row.ItemArray[0],
            dt2_Row => dt2_Row.ItemArray[2],
            dt1_Row, dt2_Row) => new { dt1_Row, dt2_Row }
       )
      .GroupBy(o => o.dt1_Row.ItemArray[0]))
{
    var row1 = grp.First().dt1_Row;
    var sum = grp.Sum(t => Convert.ToDecimal(t.dt2_Row.ItemArray[3]));
    row1.SetField(4, sum)
}

为了更加可读性,请尽量避免使用ForEach of List,但它并没有真正改善您的代码。

答案 2 :(得分:1)

这是一种方法。您可以使用GroupBy创建发票组,使用ToDictionary创建有效的InvoiceNoPaidAmount查询。然后你只需要一个循环来更新行:

var invoiceGroups = from r1 in Table1.AsEnumerable()
                    join r2 in Table2.AsEnumerable()
                    on r1.Field<int>("InvoiceNo") equals r2.Field<int>("InvoiceNo")
                    group r2 by r2.Field<int>("InvoiceNo") into InvoiceGroup
                    select InvoiceGroup;
Dictionary<int, int> invoiceSumLookup = invoiceGroups
    .ToDictionary(ig => ig.Key, ig => ig.Sum(r => r.Field<int>("Amount")));
foreach(DataRow row in Table1.Rows)
    row.SetField("PaidAmount", invoiceSumLookup[row.Field<int>("InvoiceNo")]);

请注意,如果可能且不需要,则不会从InvoiceNo删除重复的Table1行。它只是按该列对第二个表进行分组,并对所有Amount进行求和。

它修改原始表格,不需要创建新表格。