path = data + file;
if (Directory.Exists(data) && File.Exists(path))
return path;
path = dbPath + file;
if (File.Exists(path))
return path;
if ((dbPath = Path.GetDirectoryName(dbPath)) == root)
throw new FileNotFoundException("Could not find Database file: " + file);
}
}
Теперь, когда существует объект DbConnection, следует создать остальные объекты ADO.NET из категории поставщиков и потребителей данных. Эту функцию выполняет метод ConnectAndRead.
void ConnectAndRead()
{
ds = // Создайте набор данных с именем "StudsExams"
daStud = // Создайте адаптер с командой выбора всех студентов
// Установите свойство адаптера MissingSchemaAction
new OleDbCommandBuilder(daStud); // Этот странный код достраивает набор команд
// Принесите данные таблицы студентов в DataSet
// Повторите предыдущие четыре действия для таблицы экзаменов
// Создайте ограничение целостности по ссылкам ForeignKeyConstraint("StudsExams", ...
// Настройте правила этого ограничения
// Добавьте ограничение в коллекцию Constraints таблицы экзаменов
// Включите ограничение (смотрите свойство EnforceConstraints объекта DataSet)
//====== В набор данных добавьте связь между двумя таблицами
// Создайте два объекта BindingSource bsStuds = . . . и bsExams = . . .
AddStyle();
// Создайте один обработчик события RowUpdated, но так, чтобы он обрабатывал два события
// Привяжите оба объекта DataGridView к синхронизаторам bsStuds и bsExams
}
Метод ConnectAndRead создает следующие объекты ADO,NET: DataSet, два адаптера связи с базой данных (с их помощью данные переносятся в DataSet), два построителя команд CommandBuilder, которые достраивают набор команд до четырех (Select, Insert, Delete, Update), ограничение по связанному ключу, накладываемое на подчиненную таблицу экзаменов, связь (DataRelation) между таблицами и синхронизаторы (BindingSource), помогающие механизму DataBinding с учетом связи отслеживать текущие записи обеих таблиц. И, наконец, последнее, что делает метод, — это привязка двух компонентов DataGridView к источникам данных. Они инкапсулированы внутри объектов BindingSource.
Объект класса ForeignKeyConstraint добавлен в коллекцию Constraints подчиненной таблицы. После этого в ней содержатся два ограничения: UniqueConstraint и ForeignKeyConstraint. Первое ограничение действует на колонку ExamID, оно получено из базы данных при выполнении метода Fill. Второе — мы вставили вручную. Несмотря на то, что в базе это ограничение есть, оно не попадает в DataSet при выполнении метода Fill.
Таково решение разработчиков ADO.NET, о причине которого можно только догадываться. Одной из них может быть тот факт, что в процессе чтения данных ограничение может временно нарушаться. Мы можем прочесть в DataSet таблицу экзаменов и ее ссылки на студентов будут не действительны, пока не прочитана таблица Studs.
За связи между таблицами отвечает объект DataRelation. Этот класс имеет множество свойств, упрощающих работу со свзяанными таблицами. Перечислим некоторые из них: ChildTable, ChildColumns, ChildKeyConstraint, ParentTable, ParentColumns, ParentKeyConstraint. Имя связи играет важную роль в механизме DataBinding, его можно определить, или задать с помощью свойства RelationName.
· Добавьте следующий код в обработчик события ItemClicked. Обработчик должен существовать, так как настоящий проект является копией предыдущего.
void bn_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
switch (e.ClickedItem.Text)
{
case "&Save": UpdateDB(); break;
case "Cancel Changes": CancelChanges(); break;
}
}
· Добавьте метод CancelChanges, который отменяет последние (еще не закрепленные) изменения DataSet. Изменения считаются закрепленными после вызова метода AcceptChanges. Метод присутствует в трех классах: DataRow, DatTable и DataSet.
void CancelChanges()
{
bsStuds.EndEdit();
bsExams.EndEdit();
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.