Технология Microsoft ADO.NET

       

Обновление связанных таблиц


В лекции 1, при создании схемы базы данных BDTur_firm.mdb, мы определили вложенную группу "Туры" 1 - °"Сезоны" 1 - °"Путевки" 1 - °"Оплата". Далее, при экспорте этой базы в формат Microsoft SQL получился набор отдельных таблиц - мастер преобразований не перенес связи между таблицами. Рассмотрим вывод на форму и обновление этих таблиц, связанных между собой в типизированном объекте DataSet. Программное определение всех полей и параметров заняло бы слишком много места, поэтому на этот раз будем использовать визуальные средства студии. При необходимости вы сможете самостоятельно переделать приложение - изученный материал настоящей лекции позволит вам это сделать.

Запускаем SQL Server Enterprise Manager, раскрываем узел базы BDTur_firm2 и в режиме дизайна таблиц задаем ключевые поля (рис. 13.9):


Рис. 13.9.  Задание ключевых полей в SQL Server Enterprise Manager

Создайте новое Windows-приложение и назовите его "MultiFilling AndUpdating". Свойству "Size" формы устанавливаем значение "500;300". Перетаскиваем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение "Fill". Добавляем на форму элемент Panel, его свойству Dock устанавливаем значение "Bottom". На панели размещаем четыре элемента RadioButton со следующими свойствами:

radioButton1, свойствоЗначение
NamerbTours
Location26; 16
TagТуры
TextТуры
radioButton2, свойствоЗначение
NamerbSeasons
Location138; 16
TagСезоны
TextСезоны
radioButton3, свойствоЗначение
NamerbPasses
Location250; 16
TagПутевки
TextПутевки
radioButton4, свойствоЗначение
NamerbPayments
Location362; 16
TagОплата
TextОплата

Свойство "Tag" элементов RadioButton будет использоваться для задания выводимого содержимого при выборе элементов. Переходим на вкладку "Server Explorer", настраиваем подключение к базе Microsoft SQL "BDTur_firm2", из узла "Tables" перетаскиваем на форму таблицы "Туры", "Сезоны", "Путевки", "Оплата".
Соответствующие объекты DataAdapter называем "daTours", "daSeasons", "daPasses" и "daPayments". Выделив любой из объектов DataAdapter, в окне его свойств нажимаем на ссылку "Generate Dataset". В появившемся окне Generate Dataset вводим название "dsBDTur_firm" и отмечаем галочками все таблицы - они будут находиться в объекте DataSet (рис. 13.10):


Рис. 13.10.  Создание объекта DataSet

В результате получился типизированный объект DataSet. Переходим в окно "Solution Explorer", дважды щелкаем на файле dsBDTur_firm.xsd. В режиме дизайна XSD-схемы связываем таблицы по ключевым полям, оставляя названия связей по умолчанию2). Готовая схема будет иметь следующий вид (рис. 13.11):


Рис. 13.11.  Готовая XSD-схема объекта dsBDTur_firm

Переходим в код формы. В конструкторе заполняем объект 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):


увеличить изображение
Рис. 13.12.  Готовое приложение MultiFillingAndUpdating

В программном обеспечении к курсу вы найдете приложение MultiFilling AndUpdating (Code\Glava6\MultiFillingAndUpdating).

При реализации обновления связанных таблиц программным образом следует передавать изменения в особом порядке3). Обычным сценарием является добавление родительских и относящихся к ним дочерних записей в набор данных, - например, запись о новом клиенте и одна или две относящиеся к ней записи о заказах. Если сам набор данных заставляет использовать правила реляционной целостности, возникнут ошибки при отсылке дочерних записей в базу данных до создания родительских записей.

И наоборот, при удалении связанных записей из набора данных обычно необходимо отправлять обновления в обратном порядке: сначала дочерние таблицы, а потом родительские таблицы. В противном случае в наборе данных может возникнуть ошибка, так как правила ссылочной целостности не дадут удалить родительскую запись, если существуют дочерние записи.

Существует следующие правила отсылки обновлений в таблицы:

  • Дочерняя таблица: удаление записей.
  • Родительская таблица: вставка, обновление и удаление записей.
  • Дочерняя таблица: вставка и обновление записей.



Содержание раздела