DataAdapter не обновляет источник

Я столкнулся с проблемой при использовании DataAdapter, и я надеюсь, что кто-то может помочь. В основном я создаю систему, которая выглядит следующим образом:

  1. Данные считываются из источника данных (MS-Access, SQL Server или Excel), преобразуются в таблицы данных и вставляются в локальную базу данных SQL Server с помощью DataAdapters. Этот бит работает нормально. В таблице SQL-сервера есть PK, представляющий собой поле идентификации с включенным автоматическим приращением.
  2. Последующие загрузки данных считывают данные из источника и сравнивают их с тем, что у нас уже есть. Если запись отсутствует, то она добавляется (это работает нормально). Если запись отличается, ее необходимо обновить (это не работает).
  3. При загрузке разностных данных я создаю таблицу данных, которая считывает схему из целевой таблицы (сервер SQL) и гарантирует, что она имеет те же столбцы и т. д.
  4. PK в целевой таблице - это столбец 0, поэтому, когда запись вставляется, устанавливаются все значения из столбца 1 и далее (как уже упоминалось, это работает отлично). Я не меняю статус строки для элементов, которые добавляю. PK в таблице данных установлен правильно, и я могу это подтвердить.
  5. При обновлении данных я устанавливаю столбец 0 (столбец PK) в качестве значения записи, которую я обновляю, и устанавливаю все столбцы такими же, как исходные данные.
  6. Для обновленных записей я вызываю AcceptChanges и SetModified для строки, чтобы убедиться (как я думал), что приложение вызывает правильный метод.
  7. DataAdapter устанавливается с помощью SelectCommand и UpdateCommand с помощью построителя команд.

Когда я запускаю, я отслеживаю это с помощью профилировщика SQL и вижу, что команда вставки выполняется правильно, но команда обновления вообще не выполняется, что является сутью проблемы. Для справки таблица вставки будет выглядеть примерно так:

PK   Value1    Value 2    Row State
==   ======    =======    =========
124   Test1     Test 2    Added
123   Test3     Test4     Updated

Пара вещей, о которых нужно знать....

  • Я проверил это, загрузив строку, которую нужно изменить, в таблицу данных, изменив некоторые поля столбца и запустив обновление, и это работает. Однако это нецелесообразно для моего решения, потому что данные ОГРОМНЫ > 1 Гб, поэтому я не могу просто загрузить их в таблицу данных без значительного снижения производительности. Что я делаю, так это создаю таблицу данных с максимальным количеством строк 500 и запускаю обновление. Тестирование во время начальной загрузки данных показало, что это наиболее эффективно с точки зрения использования памяти и производительности. Таблица данных очищается после запуска каждой партии.

У кого-нибудь есть идеи о том, где я ошибаюсь?

заранее спасибо

Андрей

==========Обновление==============

Ниже приведен код для создания строк вставки/обновления.

    private static void AddNewRecordToDataTable(DbDataReader pReader, ref DataTable pUpdateDataTable)
    {

        // create a new row in the table

        DataRow pUpdateRow = pUpdateDataTable.NewRow();

        // loop through each item in the data reader - setting all the columns apart from the PK

        for (int addCount = 0; addCount < pReader.FieldCount; addCount++)
        {
            pUpdateRow[addCount + 1] = pReader[addCount];
        }

        // add the row to the update table

        pUpdateDataTable.Rows.Add(pUpdateRow);

    }

    private static void AddUpdateRecordToDataTable(DbDataReader pReader, int pKeyValue,
                                                   ref DataTable pUpdateDataTable)
    {
        DataRow pUpdateRow = pUpdateDataTable.NewRow();

        // set the first column (PK) to the value passed in

        pUpdateRow[0] = pKeyValue;

        // loop for each row apart from the PK row

        for (int addCount = 0; addCount < pReader.FieldCount; addCount++)
        {
            pUpdateRow[addCount + 1] = pReader[addCount];
        }

        // add the row to the table and then update it

        pUpdateDataTable.Rows.Add(pUpdateRow);
        pUpdateRow.AcceptChanges();
        pUpdateRow.SetModified();
    }

Для фактического обновления используется следующий код:

    updateAdapter.Fill(UpdateTable);
    updateAdapter.Update(UpdateTable);
    UpdateTable.AcceptChanges();

Следующее используется для создания таблицы данных, чтобы убедиться, что она имеет те же поля/типы данных, что и исходные данные.

    private static DataTable CreateDataTable(DbDataReader pReader)
    {
        DataTable schemaTable = pReader.GetSchemaTable();
        DataTable resultTable = new DataTable(<tableName>); // edited out personal info
        // loop for each row in the schema table

        try
        {

            foreach (DataRow dataRow in schemaTable.Rows)
            {

                // create a new DataColumn object and set values depending
                // on the current DataRows values

                DataColumn dataColumn = new DataColumn();
                dataColumn.ColumnName = dataRow["ColumnName"].ToString();
                dataColumn.DataType = Type.GetType(dataRow["DataType"].ToString());
                dataColumn.ReadOnly = (bool)dataRow["IsReadOnly"];
                dataColumn.AutoIncrement = (bool)dataRow["IsAutoIncrement"];
                dataColumn.Unique = (bool)dataRow["IsUnique"];

                resultTable.Columns.Add(dataColumn);
            }
        }
        catch (Exception ex)
        {
            message = "Unable to create data table " + ex.Message;
            throw new Exception(message, ex);
        }

        return resultTable;
    }

person Andrew    schedule 13.08.2012    source источник
comment
Для справки это состояние таблицы данных для 3 модификаций и 3 дополнений (столбец 1 - ПК) 238281;Изменено 238298;Изменено 238306;Изменено 238307;Добавлено 238308;Добавлено 238309;Добавлено   -  person Andrew    schedule 13.08.2012
comment
Некоторый код помог бы нам определить проблему.   -  person Holger Brandt    schedule 13.08.2012


Ответы (1)


Если кому-то интересно, мне удалось обойти проблему, но так и не удалось заставить работать адаптер данных. В основном то, что я сделал, было следующим:

  • Создайте список объектов с индексом и списком значений полей в качестве членов
  • Прочитайте строки, которые изменились, и сохраните значения из исходных данных (т. е. значения, которые перезапишут текущие значения в объекте). Кроме того, я создаю список индексов, разделенных запятыми.
  • Когда я закончу, я использую список, разделенный запятыми, в операторе sql IN, чтобы вернуть строки и загрузить их в свой адаптер данных.
  • Для каждого я запускаю запрос LINQ к индексу и извлекаю новые значения, обновляя набор данных. Это устанавливает статус строки как измененный
  • Затем я запускаю обновление, и строки обновляются правильно.

Это не самое быстрое или аккуратное решение, но оно работает и позволяет мне вносить изменения партиями.

Спасибо

Андрей

person Andrew    schedule 14.08.2012