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