Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 29.05.05 19:37
Оценка:
Доброго времени суток уважаемые.

Помогите пожалуйста разобраться, я еще новичок.

В начале делаю так:

_DbConnection.Open();
OleDbCommand _command = new OleDbCommand("SELECT * FROM Properties", _DbConnection);
_DbDataAdapter = new OleDbDataAdapter( _command );
_DbDataAdapter.Fill(_DataSet, "Properties");
DataTable dt = _DataSet.Tables["Properties"];
_DesktopProperties = new DesktopProperties( dt );
_DbConnection.Close();


затем делаю изменения в DataTable через Rows.Add и т.д.
затем пытаюсь сохранить изменения:


_DbConnection.Open();
DataTable dt = _DesktopProperties.DataTable.GetChanges();
_DataSet.Merge(dt);
_DbDataAdapter.Update(_DataSet, "Properties");
_DataSet.AcceptChanges();
_DbConnection.Close();


но Update выдает исключение: Update unable to find TableMapping['Table'] or DataTable 'Table'

Что я не так делаю ?

Заранее Спасибо.
Re: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 30.05.05 05:30
Оценка:
Народ, помогите пожалуйста. Вопрос, я так понимаю, наитупейший, но я действительно застрял.
Re[2]: Обновление БД измененным DataSet'ом
От: notacat  
Дата: 30.05.05 06:33
Оценка:
JW>Народ, помогите пожалуйста. Вопрос, я так понимаю, наитупейший, но я действительно застрял.
Проверьте в отладчике, вот после этой строчки:
DataTable dt = _DesktopProperties.DataTable.GetChanges();
что у Вас находится в таблице dt и какое имя у этой таблицы.
Re[3]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 30.05.05 15:35
Оценка:
Здравствуйте, notacat, Вы писали:

N>Проверьте в отладчике, вот после этой строчки:

N>DataTable dt = _DesktopProperties.DataTable.GetChanges();
N>что у Вас находится в таблице dt и какое имя у этой таблицы.

dt.TableName = "Properties"

а какая разница-то, что за имя у таблицы dt, если при вызове вот так:
_DbDataAdapter.Update(_DataSet);

вылезает тот же exception ?
Re[4]: Обновление БД измененным DataSet'ом
От: notacat  
Дата: 30.05.05 16:33
Оценка:
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 объявить.
С уважением, Александр. AlexKD Blog


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[5]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 01.06.05 13:03
Оценка:
В общем вот укороченный вариант:


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 );
_DbDataAdapter.Fill(_DataSet, "table1");

TestADO testado = new TestADO( _DataSet.Tables["table1"] );
testado.SetChanges();

DataTable dt = testado.DataTable.GetChanges();
if( dt != null ) 
{
    _DataSet.Merge(dt);
    _DbDataAdapter.Update(_DataSet);
    _DataSet.AcceptChanges();
}
_DbConnection.Close();


где testado

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


Exception вылезает на строке _DbDataAdapter.Update(_DataSet);
Что я делаю неправильно ?
Re[6]: Обновление БД измененным DataSet'ом
От: notacat  
Дата: 01.06.05 17:03
Оценка: 3 (1)
Действительно, во многих примерах в 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 );
        }
    }
Re[7]: Обновление БД измененным DataSet'ом
От: notacat  
Дата: 01.06.05 17:08
Оценка:
И еще, после успешного выполнения Update() AcceptChanges делается автоматически, так что эта строчка лишняя, хотя и не мешает.
Re[7]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 03.06.05 18:47
Оценка:
Все равно на Update вылезает Exception, но теперь без описания.

Кроме того я забыл сказать какой ConnectionString у меня:
"Provider='Microsoft.Jet.OLEDB.4.0';Data Source='db1.mdb';Mode=Share Deny None;User ID=Admin;"

В чем же может быть проблема ?
Re[8]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 04.06.05 07:01
Оценка:
дописав к Update
catch
Пишет что ошибка в инструкции INSERT INTO.

Посмотрев что за команду сгенерировал CommandBuilder,
увидел — INSERT INTO table1 (Name, Value) VALUES (? ,?)

почему так получилось ?
Re[9]: Обновление БД измененным DataSet'ом
От: notacat  
Дата: 04.06.05 12:25
Оценка: 3 (1)
Здравствуйте, 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 (? ,?)
Re[10]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 04.06.05 12:39
Оценка:
Здравствуйте, notacat, Вы писали:
N>Только Value — это, похоже, зарезервированное слово в Access'e, значит надо с этим что-то сделать.

сенкс фо хелп, респект
Re[10]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 04.06.05 12:44
Оценка:
Но вот еще одна проблема:

после вызова GetChanges, Merge и Update в базе появляются две одинаковые записи.
По ходу дела, в TestADO передается ссылка на DataTable["table1"], а хотелось чтобы копия. И в этом случае я могу при нескольких таблицах обновлять только нужные.
Re[11]: Обновление БД измененным DataSet'ом
От: notacat  
Дата: 04.06.05 12:45
Оценка:
JW>сенкс фо хелп, респект
not at all
Re[10]: Обновление БД измененным DataSet'ом
От: Аноним  
Дата: 04.06.05 13:01
Оценка: 3 (1)
1. Насколько я представляю, чтобы одинаковых записей не появлялось, надо чтобы в таблице было ключевое поле. Иначе невозможно определить, новая это запись, или измененная существующая.

2. Копия делается так:
  public TestADO( DataTable datatable ) 
  {
   _DataTable = datatable.Copy();
  }

Или можно в другом месте:
   TestADO testado = new TestADO( _DataSet.Tables["table1"].Copy() );
Рыжик


данное сообщение получено с www.gotdotnet.ru
ссылка на оригинальное сообщение
Re[11]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 04.06.05 13:16
Оценка:
Здравствуйте, pykhova, Вы писали:

P>1. Насколько я представляю, чтобы одинаковых записей не появлялось, надо чтобы в таблице было ключевое поле. Иначе невозможно определить, новая это запись, или измененная существующая.


P>2. Копия делается так:
  public TestADO( DataTable datatable ) 
P>  {
P>   _DataTable = datatable.Copy();
P>  } 
P>

P> Или можно в другом месте:
P>
   TestADO testado = new TestADO( _DataSet.Tables["table1"].Copy() );

P>


P>
данное сообщение получено с www.gotdotnet.ru

P>ссылка на оригинальное сообщение


я убрал строку Merge(), теперь все ок.
Re[10]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 04.06.05 13:19
Оценка:
Я извиняюсь еще раз, но опять трабл.

В документации написано, что CommandBuilder — Automatically generates single-table commands,
а у меня через один адаптер происходит Fill нескольких таблиц в один DataSet. В этом случае CommandBuilder генерирует комманды только для последней таблицы, что прошла чеорез свойство DbDataAdapter.SelectCommand.

Неужели придется для каждой таблицы делать свой адаптер и комманбилдер ?
Re[11]: Обновление БД измененным DataSet'ом
От: notacat  
Дата: 04.06.05 14:01
Оценка: 3 (1)
Здравствуйте, 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").
Re[12]: Обновление БД измененным DataSet'ом
От: John Williams  
Дата: 05.06.05 06:34
Оценка:
Я решил ситуацию таким вот образом...
Какждый экземпляр класса у меня работает только с одной таблицей.
В конструктор такого класса передается только OleDbConnection.В конструкторе инициализирую Adapter, Builder и DataTable, которые для каждого класса свои. В моем случае DataSet не нужен, поскольку Adapter может заливать данные сразу в DataTable.
Ну и каждый такой класс имеет метод Save, в котором:

DataTable changes = DataTable.GetChanges();
if( changes != null )
{
    Adapter.Update( changes );
}


и теперь все прекрасно работает, без лишнего кода.
Всем спасибо за помощь, огромный всем респект.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.