Использование OleDbDataAdapter для обновления DataTable C#
Я пытался использовать OleDbDataAdapter для обновления DataTable, но запутался в командах. Поскольку я иногда получаю информацию из разных таблиц, я не могу использовать CommandBuilder. Итак, я попытался создать команды для включения, но мне было сложно с параметрами. DataTable.GetChanges возвращает строки, которые должны использовать команду INSERT или UPDATE - я думаю, я не могу различить их. Мне нужно, чтобы вы завершили следующее:
DataTable dt = new DataTable();
OleDbDataAdapter da = new OleDbDataAdapter();
// Here I create the SELECT command and pass the connection.
da.Fill(dt);
// Here I make changes (INSERT/UPDATE) to the DataTable (by a DataGridView).
da.UpdateCommand = new OleDbCommand("UPDATE TABLE_NAME SET (COL1, COL2, ...) VALUES (@newVal1, @newVal2, ...) WHERE id=@id"); // How can I use the values of the current row (that the da is updating) as the parameters (@newVal1, @newVal2, id....)?
Большое спасибо!
2 ответа
Адаптер данных может работать в сочетании с данными. Таким образом, я на самом деле свернул свой класс в класс и работает довольно хорошо. Помимо сложностей моих вещей, вот фрагмент, который может помочь вам в этом. При добавлении параметра вы можете указать источник столбца, из которого поступают данные из таблицы данных. Таким образом, когда запись внутренне идентифицируется как "Добавленная" или "Обновленная" (или "Удаленная"), когда вы создаете команды вставки / обновления / удаления SQL, она извлекает данные из столбцов из соответствующих строк.
Например. Скажем, у меня есть DataTable, первичным ключом является "MyID" и столбцы "ColX, ColY, ColZ". Я создаю свой DataAdapter и создаю мои команды выбора, обновления, удаления, что-то вроде... (? Является заполнителем для параметров)
DataAdapter myAdapter = new DataAdapter()
myAdapter.SelectCommand = new OleDbCommand();
myAdapter.InsertCommand = new OleDbCommand();
myAdapter.UpdateCommand = new OleDbCommand();
myAdapter.DeleteCommand = new OleDbCommand();
myAdapter.SelectCommand.CommandText = "select * from MyTable where MyID = ?";
myAdapter.InsertCommand.CommandText = "insert into MyTable ( ColX, ColY, ColZ ) values ( ?, ?, ? )";
myAdapter.UpdateCommand.CommandText = "update MyTable set ColX = ?, ColY = ?, ColZ = ? where MyID = ?";
myAdapter.DeleteCommand.CommandText = "delete from MyTable where MyID = ?";
Теперь у каждого должны быть свои "Параметры". Параметры должны быть добавлены в той же последовательности, что и соответствующие им "?" местоблюститель.
// Хотя я и подставляю фиктивные значения для подготовки параметров, это просто // для целей типа данных. Это действительно изменено через адаптер данных, когда это применяет изменения
OleDbParameter oParm = new OleDbParameter( "myID", -1 );
oParm.DbType = DbType.Int32;
oParm.SourceColumn = "myID"; // <- this is where it looks back to source table's column
oParm.ParameterName = "myID"; // just for consistency / readability reference
myAdapter.SelectCommand.Parameters.Add( oParm );
сделать аналогично для остальных параметров, основанных на их типах... char, int, double, что угодно
Опять же, у меня есть класс-оболочка, который обрабатывает управление на уровне таблицы... вкратце
public myClassWrapper
{
protected DataTable myTable;
protected DataAdapter myAdapter;
... more ...
protected void SaveChanges()
{
}
}
Это сложнее, чем просто это, но во время "SaveChanges" Datatable и dataAdapter синхронизируются для своих собственных целей. Теперь сбрасываю данные. Я проверяю состояние таблицы, а затем вы можете передать всю таблицу в dataAdapter для обновления, и она будет циклически перебирать все измененные записи и выдвигать соответствующие изменения. Вам придется ловить за любые возможные ошибки данных, хотя.
myAdapter.Update( this.MyTable );
Поскольку он находит каждую "измененную" запись, он извлекает значения из источника столбца, как указано параметром, который находится в таблице, и передается адаптеру для обработки.
Надеюсь, это дало вам огромный скачок в том, что вы сталкиваетесь.
---- КОММЕНТАРИЙ НА ОБРАТНУЮ СВЯЗЬ ----
Я бы поместил ваше обновление в try/catch и зашел в программу, чтобы увидеть, что является исключением. Сообщение adn или внутреннее исключение ошибки может дать больше информации. Тем не менее, попробуйте упростить свое ОБНОВЛЕНИЕ, чтобы включить только несколько полей с элементом WHERE "Ключ".
Кроме того, и я отказался, пропустил это из первой части ответа. Возможно, вам придется указать столбец "PrimaryKey" таблицы данных. Для этого его свойство DataTable ожидает и массив столбцов, представляющих первичный ключ для таблицы. То, что я сделал, было...
// set the primary key column of the table
DataColumn[] oCols = { myDataTbl.Columns["myID"] };
myDataTbl.PrimaryKey = oCols;
Я бы закомментировал вашу полную строку обновления и все ее параметры для вашего ОБНОВЛЕНИЯ. Затем создайте его так же просто, как в моем примере: установка только 2-3 столбцов и предложение where
myAdapter.UpdateCommand.CommandText = "update MyTable set ColX = ?, ColY = ? where MyID=?";
Add Parameter object for "X"
Add Parameter object for "Y"
Add Parameter object for "MyID"
Выберите поля, такие как int или char, чтобы они имели наименьшую вероятность проблем при преобразовании типов данных, затем, как только это сработает, попробуйте добавить все свои столбцы "int" и "символьные"... затем добавьте другие. Кроме того, против какой базы данных вы собираетесь. НЕКОТОРЫЕ базы данных не используют "?" в качестве заполнителя в команде, но используют "именованные" параметры, некоторые используют
"actualColumn = @namedCol"
or even
"actualColumn = :namedCol"
Надеюсь, это заставит тебя преодолеть горб...
Вы можете использовать метод String.Format для замены @newVal1, @newVal2, ...
в вашем коде, вот так da.UpdateCommand = new OleDbCommand(String.Format("UPDATE TABLE_NAME SET (COL1, COL2, ...) VALUES ({0}, {1}, ...) WHERE id=@id",OBJECT_ARRAY_CONTAINING_VALUES_FROM_THEDG));
[Eidt за комментарий]
Чтобы справиться с row[0]
, row[1]
вам нужен цикл вроде:
for(i=0; i<rows.Count; i++)
{
da.UpdateCommand = new OleDbCommand(String.Format("UPDATE
...",row[i]);
da.Update(dt);
}