Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Ошибка добавления записей в дочернюю таблицу C# + Access

58K
20 апреля 2010 года
live22h
3 / / 20.04.2010
Здравствуйте,
вопрос наверняка решается очень просто, но никак не пойму в чем дело... Проблема такая: Есть БД Access содержащая две связанные 1:М таблицы Таб1 и Таб2, в приложении WindowsForms добавляю новый источник данных... на форму кидаю два грида, первый отображает Таб1, второй связь между Таб1 и Таб2. Во время исполнения записи добавляются, однако при попытке сохранить новые записи выходит ошибка "Невозможно добавление или изменение записи. Для обеспечения целостности данных необходимо наличие связанной записи в таблице имя_таблицы". В программе никакого кода кроме Таб1TableAdapter.Update(имя_датасета) и Таб2TableAdapter.Update(имя_датасета) нет. В метод пособии прочитал что этого должно быть достаточно... Подскажите в чем моя ошибка?
Заранее спасибо!

PS
Руки не кривые и голова на месте, не откажусь от ссылки на толковую литературу по работе с БД. На C# пересел недавно, раньше писал в Delphi, поэтому пока плаваю в некоторых вопросах.
842
23 апреля 2010 года
sigmov
301 / / 16.09.2008
Сталкивался с данной проблемой. Долго решал.

В ADO.NET необходимо не только сказать адаптеру "обновись", но и сказать ему КАК это сделать.

К счастью для структурированных таблиц ( в которых есть закрепленные ключи ) команду обновление можно получить программно.

Фрагмент соединения с БД и получения команд обновления\вставки\удаления
Код:
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + textBox_DBpath.Text);
            conn.Open();
            TableView.dbAdapter = new OleDbDataAdapter("SELECT * FROM " + TableView.listViewItem.Text, conn);
            OleDbCommandBuilder ComBilder = new OleDbCommandBuilder(TableView.dbAdapter);
            try
            {
                TableView.dbAdapter.UpdateCommand = ComBilder.GetUpdateCommand();
                TableView.dbAdapter.InsertCommand = ComBilder.GetInsertCommand();
                TableView.dbAdapter.DeleteCommand = ComBilder.GetDeleteCommand();
            }
            catch (InvalidOperationException ioe)
            {
                MessageBox.Show("Доступ только для чтения\n\r" + ioe.Message, "Доступен только для чтения", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                TableView.dataGridView.ReadOnly = true;
                TableView.Text += " ReadOnly(!!!)";
            }
            conn.Close();

И теперь само обновление по нажатию save'ика
Код:
private void toolSaveChanged_Click(object sender, EventArgs e)
        {
            this.dataGridView.CancelEdit();
            this.dataGridView.ClearSelection();
            try
            {
                this.dbAdapter.Update(this.dataGridView.DataSource as DataTable);
                (this.dataGridView.DataSource as DataTable).AcceptChanges();
            }
            catch (InvalidOperationException ioe)
            {
                MessageBox.Show("Ошибка обновления данных базы\n\r" + ioe.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }



Могу скинуть полный код ( прикрепить к мессейджу не удалось - дюже большой ) - так что если понадобиться - напишите в личку.
58K
26 апреля 2010 года
live22h
3 / / 20.04.2010
Ошибка была перед глазами, но я не знал как ее устранить... Оказалось, что все очень просто. В схеме данных значения шага увеличения инкремента было равно -1, при обновлении набора данных главной таблицы значение инкремента записи становилось положительным, а записи подчиненной таблицы продолжали ссылаться на запись с отрицательным инкрементным полем главной таблицы, которой после обновления уже не было.
Решение нашел случайно, просто стал изучать схему данных и обнаружил что шаг инкремента -1, не знаю почему так сделано по умолчанию, но наверно у разработчиков были веские аргументы для этого.
После исправления данные стали сохраняться, для этого достаточно всего двух строк теста вида:
TabAdapter.Update(Главная_Таблица);
TabAdapter.Update(Подчиненная_Таблица);

PS
Спасибо, за то что откликнулись!
Тема закрыта
61K
09 мая 2010 года
NaMhsIRI
1 / / 09.05.2010
Добрый день. Мне хотелось бы добавить вопрос по этой теме.
live22h не зря заметил, что у разработчиков были веские аргументы, что бы по умолчанию использовать инкремент с шагом -1. Дело в том что это, так называемые, фиктивные индексы. По умолчанию они не передаются в базу данных, так как база сама генерирует индексы ключа. И что бы не вводить в заблуждение пользователей обычно их делают отрицательными.

Обычно инкремент индекса в базе данных происходит с шагом +1, поэтому решение проблемы, предложенное live22h, в какой то степени, верное. Фактически мы делаем шаг инкремента в нашем датасет таким же как и в базе. Но все таки это не лучшее решение.

Приведу пример. Допустим у нас есть 2 связанные таблицы (родительская с первичным ключом, и дочерняя). Добавим строку в родительскую таблицу, пусть там уже было 10 записей, поэтому значение ключа у новой строки будет 11. Затем добавим строку в дочернюю таблицу, у нее есть поле которое ссылается на индекс строки из родительской таблицы: 11.
Затем сделаем это еще раз. Еще одну строку в родительскую - значение ключа станет 12, и еще одну строку в дочернюю таблицу с ссылкой на строку родительской таблицы с индексом 12. А теперь удалим первые добавленные строки из таблиц, а уже потом попробуем передать новые данные в базу.

Возникнет ошибка, база добавит новую строку в родительскую таблицу и установит значение ключа равным 11. Однако в дочерней таблице мы все еще ссылаемся на строку с индексом 12.

А теперь вопрос. Как передать правильные значения ключа в дочернюю таблицу, желательно что бы обновление данных происходило за один раз.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог