Да, вы можете сделать это с LINQ, я бы сделал это:
var dataRows1 = st1.AsEnumerable().Select(r => new {
Id = r["id"], Val1 = r["val1"], Val2 = r["val2"] });
var dataRows2 = st2.AsEnumerable().Select(r => new {
Id = r["id"], Val1 = r["val1"], Val2 = r["val2"] });
Это дает вам IEnumerable<T>
анонимных типов, с которыми можно сравнить. Затем вы можете сделать это:
var dt2NotInDt1 = dataRows2.Where(r2 => !dataRows1.Any(r1 => r1.Equals(r2));
Обратите внимание, что это предполагает, что в качестве критерия сравнения используются все значения в строках (id
в том числе).
Также обратите внимание на вызов Equals
. Анонимные типы переопределяют метод Equals
, чтобы обеспечить сравнение значений по всем свойствам анонимного типа. Из раздела «Анонимные типы» Руководства по программированию в C # :
Поскольку методы Equals
и GetHashCode
для анонимных типов
определены в терминах Equals
и GetHashcode
методов
свойства, два экземпляра одного и того же анонимного типа равны, только если
все их свойства равны.
Вы можете упростить эту логику в зависимости от ограничений. Например, если есть первичный ключ (или какой-то уникальный идентификатор строки), вы можете поместить строки в словарь с ключом на это значение, а затем выполнить поиск на основе этого.
В вашем случае, если id
уникально, вы можете сделать это (после первых двух строк вверху):
var dataRows1Map = dataRows1.ToDictionary(r => r.Id);
Это даст вам карту, на которой вы сможете выполнить поиск (я переключаюсь на синтаксис запроса, так как считаю, что он немного более читабелен).
var dt2NotInDt1 =
for r2 in dataRows2
let r1Exists = dataRows1Map.ContainsKey(r2.Id)
let r1 = r1Exists ? dataRows1Map[r2.Id] : null
where
// Rows that don't have a primary key in the first set.
!r1Exists ||
// Rows that are different.
!r1.Equals(r2)
select r2;