Использование 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....)?

Большое спасибо!


person gavra    schedule 16.04.2012    source источник


Ответы (2)


Адаптер данных может работать совместно с таблицей данных. Таким образом, я фактически объединил свой класс в класс и работает довольно хорошо. Помимо сложностей моих вещей, вот фрагмент, который может вам помочь. При добавлении параметра вы можете определить источник столбца, из которого поступают данные ИЗ DataTable. Таким образом, когда запись внутренне идентифицируется как «Добавлена» или «Обновлена» (или «Удалена»), при создании команд SQL Insert/Update/Delete она будет извлекать данные из столбцов из соответствующих строк.

Например. Скажем, у меня есть 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 и зашел в программу, чтобы увидеть, что это за исключение. Сообщение и/или внутреннее исключение ошибки могут дать дополнительную информацию. Однако попытайтесь упростить ОБНОВЛЕНИЕ, включив в него только НЕСКОЛЬКО полей с элементом 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» и «character»… затем добавьте любые другие. Кроме того, против какой базы данных вы идете. НЕКОТОРЫЕ базы данных не используют "?" в качестве заполнителя в команде, но используют «именованные» параметры, некоторые используют

"actualColumn = @namedCol"
or even
"actualColumn = :namedCol"

Надеюсь, это поможет вам преодолеть горб ...

person DRapp    schedule 17.04.2012
comment
Спасибо. У меня все еще есть проблема с выполнением метода Update. Пишет, что мне не хватает значения одного из параметров. Возможно ли, что проблема в том, что я не использую набор данных? (Я просто использую DataTable и привязываю его к DataGridView с помощью объекта BindingSource). Спасибо (: - person gavra; 19.04.2012
comment
@gavra, посмотри расширенный ответ, дай мне знать. - person DRapp; 19.04.2012
comment
Большое спасибо! На этот раз проблема заключалась в том, что я пытался обновить столбец первичного ключа. Теперь он отлично работает, я его оберну и буду использовать в своем проекте. Хорошего дня! - person gavra; 19.04.2012

Вы можете использовать метод 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);

}

person Joshua Drake    schedule 16.04.2012
comment
Спасибо за ваш ответ. Я знаю этот метод. Проблема заключается в обновлении всех строк в таблице данных, и у меня есть только одна команда обновления. Например, я мог бы использовать в качестве параметра rows[0].myColumn, после чего параметр должен быть rows[1].myColumn. Я также заметил, что есть способ обновления, даже не определяя команду обновления. Только не придумал как. - person gavra; 17.04.2012