JW>Народ, помогите пожалуйста. Вопрос, я так понимаю, наитупейший, но я действительно застрял.
Проверьте в отладчике, вот после этой строчки:
DataTable dt = _DesktopProperties.DataTable.GetChanges();
что у Вас находится в таблице dt и какое имя у этой таблицы.
Здравствуйте, notacat, Вы писали:
N>Проверьте в отладчике, вот после этой строчки: N>DataTable dt = _DesktopProperties.DataTable.GetChanges(); N>что у Вас находится в таблице dt и какое имя у этой таблицы.
dt.TableName = "Properties"
а какая разница-то, что за имя у таблицы dt, если при вызове вот так:
JW>а какая разница-то, что за имя у таблицы dt, если при вызове вот так: JW>
JW>_DbDataAdapter.Update(_DataSet);
JW>
JW>вылезает тот же exception ?
А такая, что когда Вы создавали датасет и мэппинг к нему, то там указывалось имя таблицы "Properties",
а судя по приведнному exception'у, при обновлении она у Вас уже называется "Table".
Очень желательно, чтобы она называлась "Properties", если Вы хотите, чтобы база обновилась.
Если действительно в этом дело, то можно перед Update этой таблице задать правильное имя.
Хотя точно сказать не могу, потому что неизвестно, что еще могло с этой таблицей случиться в процессе работы.
Может DesktopProperties возвращает таблицу с другой структурой.
Обновление БД измененным DataSet'ом
От:
Аноним
Дата:
31.05.05 05:00
Оценка:
А если так:
_DbConnection.Open();
DataSet _DataSet2= _DesktopProperties.DataTable.GetChanges();
_DbDataAdapter.Update(_DataSet, "Properties");
_DbDataAdapter2.Update(_DataSet2);
_DataSet.AcceptChanges();
_DataSet2.AcceptChanges();
_DbConnection.Close();
Соответственно, еще нужно _DbDataAdapter2 объявить.
Действительно, во многих примерах в MSDN написано так: _DbDataAdapter.Update(_DataSet),
но я так никогда не делала. Видимо, что-то тут не срослось, потому что в датасете одна таблица, имя у нее правильное, а в исключении все равно написано, что нет мэппинга для таблицы c каким-то левым именем.
Укажите явно имя таблицы в команде Update. Вот рабочий вариант (попробовала):
OleDbConnection _DbConnection = new OleDbConnection();
_DbConnection.ConnectionString = ...;
DataSet _DataSet = new DataSet();
_DbConnection.Open();
OleDbCommand _command;
_command = new OleDbCommand("SELECT * FROM table1", _DbConnection);
OleDbDataAdapter _DbDataAdapter = new OleDbDataAdapter( _command );
OleDbCommandBuilder _cb = new OleDbCommandBuilder( _DbDataAdapter ); // Строит команды вставки, обновления и удаления
_DbDataAdapter.Fill(_DataSet, "Portfolio");
TestADO testado = new TestADO( _DataSet.Tables["Portfolio"] );
testado.SetChanges();
DataTable dt = testado.DataTable.GetChanges();
if( dt != null )
{
_DataSet.Merge(dt);
_DbDataAdapter.Update(_DataSet, "table1"); // Явно задать имя таблицы.
_DataSet.AcceptChanges();
}
_DbConnection.Close();
public class TestADO
{
private DataTable _DataTable;
public DataTable DataTable
{
get
{
return _DataTable;
}
}
public TestADO( DataTable datatable )
{
_DataTable = datatable;
}
public void SetChanges()
{
DataRow _row = _DataTable.NewRow();
_row.BeginEdit();
_row["Name"] = "Test";
_row["Value"] = "Value";
_row.EndEdit();
_DataTable.Rows.Add( _row );
}
}
Все равно на Update вылезает Exception, но теперь без описания.
Кроме того я забыл сказать какой ConnectionString у меня:
"Provider='Microsoft.Jet.OLEDB.4.0';Data Source='db1.mdb';Mode=Share Deny None;User ID=Admin;"
Здравствуйте, John Williams, Вы писали:
JW>дописав к Update JW>catch JW>Пишет что ошибка в инструкции INSERT INTO.
JW>Посмотрев что за команду сгенерировал CommandBuilder, JW>увидел — INSERT INTO table1 (Name, Value) VALUES (? ,?)
Вообще, команда сгенерировалась нормальная. Т.е. CommandBuilder прочитал из базы структуру таблицы и сделал команду.
Только Value — это, похоже, зарезервированное слово в Access'e, значит надо с этим что-то сделать.
Могу посоветовать два варианта:
— поменять название столбца в базе
— сделать свою команду (или изменить текст команды в сгенерированной команде) так, чтобы название этого столбца было в квадратных скобках: INSERT INTO table1 (Name, [Value]) VALUES (? ,?)
после вызова GetChanges, Merge и Update в базе появляются две одинаковые записи.
По ходу дела, в TestADO передается ссылка на DataTable["table1"], а хотелось чтобы копия. И в этом случае я могу при нескольких таблицах обновлять только нужные.
1. Насколько я представляю, чтобы одинаковых записей не появлялось, надо чтобы в таблице было ключевое поле. Иначе невозможно определить, новая это запись, или измененная существующая.
2. Копия делается так:
public TestADO( DataTable datatable )
{
_DataTable = datatable.Copy();
}
Или можно в другом месте:
TestADO testado = new TestADO( _DataSet.Tables["table1"].Copy() );
Здравствуйте, pykhova, Вы писали:
P>1. Насколько я представляю, чтобы одинаковых записей не появлялось, надо чтобы в таблице было ключевое поле. Иначе невозможно определить, новая это запись, или измененная существующая.
P>2. Копия делается так:
В документации написано, что CommandBuilder — Automatically generates single-table commands,
а у меня через один адаптер происходит Fill нескольких таблиц в один DataSet. В этом случае CommandBuilder генерирует комманды только для последней таблицы, что прошла чеорез свойство DbDataAdapter.SelectCommand.
Неужели придется для каждой таблицы делать свой адаптер и комманбилдер ?
Здравствуйте, John Williams, Вы писали:
JW>Я извиняюсь еще раз, но опять трабл.
JW>В документации написано, что CommandBuilder — Automatically generates single-table commands, JW>а у меня через один адаптер происходит Fill нескольких таблиц в один DataSet. В этом случае CommandBuilder генерирует комманды только для последней таблицы, что прошла чеорез свойство DbDataAdapter.SelectCommand.
JW>Неужели придется для каждой таблицы делать свой адаптер и комманбилдер ?
Либо так, либо можно обойтись без билдера и самостоятельно сделать команды для вставки, обновления и удаления.
Попробуйте где-нибудь в сторонке сделать типизированный датасет и адаптер для Вашего случая, а потом посмотрите, какой там код получается (поищите в MSDN статьи "Creating Typed Datasets with the Component Designer" и "Walkthrough: Mapping Data Source Tables to Dataset Tables").
Я решил ситуацию таким вот образом...
Какждый экземпляр класса у меня работает только с одной таблицей.
В конструктор такого класса передается только OleDbConnection.В конструкторе инициализирую Adapter, Builder и DataTable, которые для каждого класса свои. В моем случае DataSet не нужен, поскольку Adapter может заливать данные сразу в DataTable.
Ну и каждый такой класс имеет метод Save, в котором: