Передача изменений в базу данных при помощи хранимых процедур. Объект CommandBuilder
Обновление связанных таблиц
В "Элементы работы с базами данных" , при создании схемы базы данных BDTur_firm.mdb, мы определили вложенную группу "Туры" 1 - °"Сезоны" 1 - °"Путевки" 1 - °"Оплата". Далее, при экспорте этой базы в формат Microsoft SQL получился набор отдельных таблиц - мастер преобразований не перенес связи между таблицами. Рассмотрим вывод на форму и обновление этих таблиц, связанных между собой в типизированном объекте DataSet. Программное определение всех полей и параметров заняло бы слишком много места, поэтому на этот раз будем использовать визуальные средства студии. При необходимости вы сможете самостоятельно переделать приложение - изученный материал настоящей лекции позволит вам это сделать.
Запускаем SQL Server Enterprise Manager, раскрываем узел базы BDTur_firm2 и в режиме дизайна таблиц задаем ключевые поля (рис. 13.9):
Создайте новое Windows-приложение и назовите его "MultiFilling AndUpdating". Свойству "Size" формы устанавливаем значение "500;300". Перетаскиваем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Добавляем на форму элемент Panel, его свойству Dock устанавливаем значение "Bottom". На панели размещаем четыре элемента RadioButton со следующими свойствами:
Свойство "Tag" элементов RadioButton будет использоваться для задания выводимого содержимого при выборе элементов. Переходим на вкладку "Server Explorer", настраиваем подключение к базе Microsoft SQL "BDTur_firm2", из узла "Tables" перетаскиваем на форму таблицы "Туры", "Сезоны", "Путевки", "Оплата". Соответствующие объекты DataAdapter называем "daTours", "daSeasons", "daPasses" и "daPayments". Выделив любой из объектов DataAdapter, в окне его свойств нажимаем на ссылку "Generate Dataset". В появившемся окне Generate Dataset вводим название "dsBDTur_firm" и отмечаем галочками все таблицы - они будут находиться в объекте DataSet (рис. 13.10):
В результате получился типизированный объект DataSet. Переходим в окно "Solution Explorer", дважды щелкаем на файле dsBDTur_firm.xsd. В режиме дизайна XSD-схемы связываем таблицы по ключевым полям, оставляя названия связей по умолчанию2Если вы забыли, как это делается, вернитесь к пятой Главе.. Готовая схема будет иметь следующий вид (рис. 13.11):
Переходим в код формы. В конструкторе заполняем объект DataSet:
public Form1() { InitializeComponent(); //Отключаем ограничения на время заполнения объекта DataSet dsBDTur_firm1.EnforceConstraints = false; sqlConnection1.Open(); //Заполняем объект DataSet daTours.Fill(dsBDTur_firm1); daSeasons.Fill(dsBDTur_firm1); daPasses.Fill(dsBDTur_firm1); daPayments.Fill(dsBDTur_firm1); sqlConnection1.Close(); //Включаем ограничения dsBDTur_firm1.EnforceConstraints = true; //Привязываем все обработчики всех элементов RadioButton к одному rbTours.CheckedChanged += new EventHandler(rbTours_CheckedChanged); rbSeasons.CheckedChanged += new EventHandler(rbTours_CheckedChanged); rbPasses.CheckedChanged += new EventHandler(rbTours_CheckedChanged); rbPayments.CheckedChanged += new EventHandler(rbTours_CheckedChanged); }
Обратите внимание на порядок заполнения DataSet. Вначале поступают данные из родительских таблиц, затем из дочерних. Это позволяет не нарушать целостность записей. Создаем метод rbTours_CheckedChanged, в котором реализуем переключатель содержимого объекта DataGrid:
private void rbTours_CheckedChanged(object sender, EventArgs e) { RadioButton rb = (RadioButton)sender; if(!rb.Checked) return; dataGrid1.DataSource = dsBDTur_firm1; dataGrid1.DataMember = rb.Tag.ToString(); }
В обработчике события Closing формы передаем изменения в базу данных:
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { try { sqlConnection1.Open(); daTours.Update(dsBDTur_firm1); daSeasons.Update(dsBDTur_firm1); daPasses.Update(dsBDTur_firm1); daPayments.Update(dsBDTur_firm1); } catch(Exception ex) { MessageBox.Show(ex.ToString()); } finally { sqlConnection1.Close(); } }
Здесь снова вначале передаются изменения из родительских таблиц, затем из дочерних. В готовом приложении можно вставлять, изменять и удалять записи (рис. 13.12):
В программном обеспечении к курсу вы найдете приложение MultiFilling AndUpdating (Code\Glava6\MultiFillingAndUpdating).
При реализации обновления связанных таблиц программным образом следует передавать изменения в особом порядке3Этот фрагмент является переводом статьи "Database Updates from Datasets" из MSDN (заголовок раздела "Updating Related Tables").. Обычным сценарием является добавление родительских и относящихся к ним дочерних записей в набор данных, - например, запись о новом клиенте и одна или две относящиеся к ней записи о заказах. Если сам набор данных заставляет использовать правила реляционной целостности, возникнут ошибки при отсылке дочерних записей в базу данных до создания родительских записей.
И наоборот, при удалении связанных записей из набора данных обычно необходимо отправлять обновления в обратном порядке: сначала дочерние таблицы, а потом родительские таблицы. В противном случае в наборе данных может возникнуть ошибка, так как правила ссылочной целостности не дадут удалить родительскую запись, если существуют дочерние записи.
Существует следующие правила отсылки обновлений в таблицы: