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

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

  1. Данные считываются из источника данных (MS-Access, SQL Server или Excel), преобразуются в таблицы данных и вставляются в локальную базу данных SQL Server с помощью DataAdapters. Этот бит отлично работает. В таблице SQL-сервера есть PK, представляющий собой поле идентификации с автоматическим приращением, установленным на on.
  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 строками и запуск обновления. Тестирование во время начальной загрузки данных показало, что это наиболее эффективно с точки зрения использования памяти и производительности. Таблица данных очищается после запуска каждого пакета.

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

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

Эндрю

==========Update==============

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

    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;
    }

1 ответ

Решение

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

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

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

Спасибо

Эндрю

Другие вопросы по тегам