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

Если у объекта BindingSource  не задано свойство Filter и пользователю запрещено использовать функцию сортировки записей в DataGridView, то эта задача является очень простой – индекс записи в таблице совпадает  со свойством CurrentRow.Index объекта DataGridView.

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

Значение это поля можно извлечь из объекта DataGridView при помощи индексатора, например:

int ind = (int)dataGridView1[0, dataGridView1.CurrentRow.Index].Value;

Здесь первичный ключ является нулевой колонкой таблицы и является целочисленным значением.

Для таблиц, имеющих первичный ключ, при автоматическом создании DataSet будет сформирован метод Find, который позволяет определить запись по значению первичного ключа. Найденная запись удаляется при помощи метода Delete.

Метод Delete физически из DataSet запись не удаляет, а только помечает как удаленную. При выполнении метода Update автоматически формируются и выполняются SQL запросы на удаление таких записей из базы данных.

Если воспользоваться компонентом BindingNavigator задача удаления записей существенно упрощается. Это компонент обеспечивает навигацию по строкам таблицы. При переносе такого объекта на форму автоматически создаются кнопки, позволяющие выполнять навигацию между строками, а также кнопки удаления и добавления новых записей.

В том случае, если на форме необходимо отобразить несколько таблиц, на форму следует поместить необходимое количество DataGridView и при создании источника данных включить в него все таблицы. При определении источника данных для каждого объекта DataGridView задать необходимую таблицу из объекта DataSet.

Если таблицы связаны между собой отношением "один ко многим" задача усложняется.

Первоначально надо в дизайнере DataSet установить связи между таблицами. При работе в графическом интерфейсе дизайнера создаются объекты Relation, которые отображают связи между таблицами.

Далее необходимо создать источник данных для таблицы, стоящей на верхнем уровне иерархии. При создании такого источника просто выбирается таблица из DataSet. При этом, как было отмечено выше, автоматически создается объект BindingSource.

При задании источника данных подчиненной таблицы надо выбрать в качестве источника данных (DataSource) объект BindingSource таблицы верхнего уровня иерархии, а в качестве DataMember – связь между таблицами (эта связь отображается дизайнером как элемент объекта BindingSoruce). При этом автоматически будет создан еще один источник данных для второй таблицы.

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

При написании операторов Update для подчиненных таблиц необходимо учитывать правила, приведенные в документации фирмы Microsoft.

Простейшим является следующее правило: сначала выполняется метод Update объекта TableAdapter для дочерней таблицы, а затем для родительской.

Более сложное правило формулируется следующим образом:

1. Удаление записей дочерней таблицы

2. Вставка, корректировка и удаление записей родительской таблицы

3. Вставка и корректировка записей дочерней таблицы

Для того, чтобы обновить в базе данных две связанные таблицы используя TableAdapter необходимо выполнить следующие действия:

1. Создать три временные таблицы для каждого типа записей (добавленные, откорректированные и удаленные)

2. Вызвать метод Update для каждого типа записей отдельно по правилам, сформулированным выше.

Ввиду того, что при корректировке могут возникнуть исключения, операторы Update следует заключать в блок try/catch.

Ниже приведен пример обновления двух связанных между собой таблиц OrdersDataTable (дочерняя) и Customers (родительская) набора данных  NorthwindDataSet.

NorthwindDataSet.OrdersDataTable deletedChildRecords =

(NorthwindDataSet.OrdersDataTable)northwindDataSet.Orders.GetChanges(DataRowState.Deleted);

NorthwindDataSet.OrdersDataTable newChildRecords =

(NorthwindDataSet.OrdersDataTable)northwindDataSet.Orders.GetChanges(DataRowState.Added);

NorthwindDataSet.OrdersDataTable modifiedChildRecords =

(NorthwindDataSet.OrdersDataTable)northwindDataSet.Orders.GetChanges(DataRowState.Modified);

try

{

if (deletedChildRecords != null)

{

ordersTableAdapter.Update(deletedChildRecords);

}

customersTableAdapter.Update(northwindDataSet.Customers);

if (newChildRecords != null)

{

ordersTableAdapter.Update(newChildRecords);

}

if (modifiedChildRecords != null)

{

ordersTableAdapter.Update(modifiedChildRecords);

}

northwindDataSet.AcceptChanges();

}

catch (Exception ex)

{

MessageBox.Show("Ошибка во время процесса обновления");

// Коды по обработке ошибки

}

finally

{

if (deletedChildRecords != null)

{

deletedChildRecords.Dispose();

}

if (newChildRecords != null)

{

newChildRecords.Dispose();

}

if (modifiedChildRecords != null)

{

modifiedChildRecords.Dispose();

}

}