Сравните два поля DataTable Multi - PullRequest
0 голосов
/ 19 августа 2011
        DataTable dt1 = new DataTable();
        DataTable dt2 = new DataTable();

        dt1.Columns.Add("id");
        dt2.Columns.Add("id");

        dt1.Columns.Add("val1");
        dt2.Columns.Add("val1");

        dt1.Columns.Add("val2");
        dt1.Columns.Add("val2");


        dt1.Rows.Add(new string[] { "1", "a", "a1" });
        dt1.Rows.Add(new string[] { "2", "b", "b1" });
        dt1.Rows.Add(new string[] { "", "b", "b1" });
        dt1.Rows.Add(new string[] { "4", "", "c1" });


        dt2.Rows.Add(new string[] { "1", "a", "a1" });
        dt2.Rows.Add(new string[] { "2", "b", "b1" });
        dt2.Rows.Add(new string[] { "3", "c", "c1" });
        dt2.Rows.Add(new string[] { "3", "c", "c1" });
        dt2.Rows.Add(new string[] { "4", "d", "d1" });
        dt2.Rows.Add(new string[] { "5", "e", "e1" });

результат должен содержать только значения, которых нет в dt1. Можем ли мы сделать это с linq

1 Ответ

1 голос
/ 19 августа 2011

Да, вы можете сделать это с 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;
...