2013-12-19 6 views
2

У меня есть две таблицы 1 и таблица2, столбцы которых со значениями приведены ниже: Это две таблицы: Я хочу обновить «PaidAmount» в таблице1. Присоединитесь к столбцу «InvoiceNo» в обеих таблицах.Присоединиться и обновить DataTable

Table1:

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  

Table2:

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 

Мой желаемый DataTable должен быть таким:

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 

Как получить нужный мне таблицу?

ответ

1

Ваше соединение дает вам список нескольких строк row1, row2.
Итак, вы перебираете каждую пару, первый раз для invoiceNo1, row1.PaidAmount = 5000, затем ваш цикл продолжается, а второй раз row1.PaidAmount = 2000, поэтому ваш результат.

Вы хотите просуммировать значения РАЗМЕРА row2, так что после присоединения, вы должны сгруппировать Данные по 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) 
} 

Для более readibility, старается избегать использования ForEach Списка , это не улучшает ваш код.

+0

Это дает ошибку: не может неявно преобразовать тип 'object' в 'decimal'. – thevan

+0

Я обновил код с преобразованием из объекта в int. Каков тип поля Сумма? –

+0

decimal - тип данных как для суммы, так и для оплаты. – thevan

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])); 
+0

Это дает следующее сообщение об ошибке: «Ошибка \t \t 1 Оператор„+“не может быть применена к операндам типа„объект“и" объект» – thevan

+0

Вы должны были бы получить значение объекта в ItemArray. Я не знаю, что такое базовый тип элементов в ItemArray. Вероятно, вам нужно будет применить его к соответствующему типу. – Carth

1

Вот один из подходов. Вы можете использовать GroupBy, чтобы создать группы счетов-фактур и ToDictionary, чтобы создать эффективный поиск InvoiceNo до PaidAmount. Тогда вам просто нужно цикл обновления строки:

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 s.

Он изменяет исходную таблицу и не требует создания новой.

Смежные вопросы