Разница между двумя таблицами данных - PullRequest
0 голосов
/ 26 июня 2009

У меня есть две таблицы данных. DataTable dtRequired и DataTable dtResult.

Я хочу вывести таблицу данных, которая содержит строки, которых не было в dtResponse, но которые были найдены в dtRequired.

Подход 1 Мы использовали алгоритм, указанный по следующему адресу http://weblogs.sqlteam.com/davidm/archive/2004/01/19/739.aspx. И этот алгоритм считается одним из самых медленных в нашем профилировании.

Подход 2 Итак, я попытался заменить вышеприведенный алгоритм чем-то, что описано ниже. dtRequired индексируется в столбцах, которые я использую ниже, чтобы Найти строку.

    if (dtResult.Rows.Count > 0)
    {
        lock (dtResult)
        {
            DataRow rowfound = null;
            for (int i = 0; i < dtResult.Rows.Count; i++)
            {
                DataRow row = dtResult.Rows[i];
                rowfound = dtRequired.Rows.Find(new object[] { row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8] });
                if (rowfound != null)
                {
                    dtRequired.Rows.Remove(rowfound);
                }
            }                        
        }
    }

Однако вышеприведенный фрагмент занимает больше времени, чем Подход 1 . Подход 2 занимает ~ 3 секунды для dtResult с 1250 строками и dtRequired с 4500 строками.

Что-то не так с подходом, о котором я говорил выше? Есть ли лучший способ добиться этого?

Ответы [ 3 ]

1 голос
/ 26 июня 2009

Это ссылка на страницу MSDN, которая использует LINQ to DataSet для получения строк, которые появляются в обеих таблицах данных. В этом примере используется Пересечение . Я думаю, что вы можете изменить его, используя за исключением . Я не знаю, будет ли производительность лучше или нет.

0 голосов
/ 28 сентября 2009
  1. Вы сказали, что ваш зацикленный метод Find () менее эффективен, чем подход 1 http://weblogs.sqlteam.com/davidm/archive/2004/01/19/739.aspx.

  2. Я видел, как люди говорили об ADO.NET 3.5 и LINQ, предполагая, что у вас есть производственный LINQ для или используется итеративный метод для заполнения какого-либо универсального контейнера.

  3. Интересно, будет ли творческое использование HashTable более быстрым в вычислительном отношении (реальный мир, а не теория)? В случае Diff (tbl1, tb2) просто заполните хеш tbl2, затем итеративно добавьте члены tbl1. Для каждого успеха также добавьте копию члена в выходной (разностный) массив для отображения / возврата. Очевидно, что для каждой ошибки она уже существует, поэтому не выводите / не возвращайте это значение.

Дайте мне знать, я переделаю свой код, если вы подтвердите, что 3 - самый быстрый. Я сравниваю коллекцию DirectoryServices.FindAll () с SqlDataReader (), и я полагаю, что LINQ to Active Directory находится в бета-версии третьей стороны. Поэтому мне нужен одобренный метод «производства», максимально эффективный при 15 000 объектов.

0 голосов
/ 26 июня 2009
private IEnumerator<object[]> GetEnumerator( DataTable dtRequired, DataTable dtResponse )
{
    foreach( DataRow row in dtResponse.Rows )
    {
        // use the columns of the primary key below
        if( dtResult.Rows.Contains( new object[] { row[0], row[2], row[4] } ) )
            continue;
        else
            yield return row.ItemArray;

    }
}

private void GetComplement( DataTable dtRequired, DataTable dtResponse, out DataTable dtResult )
{
    DataTable dtResult = dtRequired.Clone();

    foreach( object[] items in GetEnumerator( dtRequired, dtResponse ) )
    {
        dtResult.Rows.Add( items );
    }

    return;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...