ADO.NET. Управление базами данных. Связь по схеме OLE DB провайдера. Коррекция стилей DataGridView, страница 33

   Debug.WriteLine("Studs deleted: " + nRows);

  }

  void HandleEmptyFields (DataRow row, DataTable dt)

  {

   for (int i = 1; i < dt.Columns.Count; i++)

   {

    if (row[i] is DBNull)

    {

      DataColumn col = dt.Columns[i];

      switch (col.DataType.Name)

      {

      case "Boolean": row[i] = bool.FalseString; break;

      case "DateTime": row[i] = DateTime.MinValue; break;

      case "Byte": row[i] = byte.MinValue; break;

      default: row[i] = "N/A"; break;

      }

    }

   }

  }

  void bn_ItemClicked(object sender, ToolStripItemClickedEventArgs e)

  {

   switch (e.ClickedItem.Text)

   {

    case "&Save":

//      ShowChanges(0);

//      ShowChanges(1);

      try

      {

        cn.Open();

        UpdateDB();

      }

      catch (Exception ex) { MessageBox.Show(ex.Message); }

      finally

      {

        if (cn.State == ConnectionState.Open)

           cn.Close();

        changes.Clear();

      }

      break;

    case "Cancel Changes": CancelChanges(); break;

    case "Load from DB": LoadFromDB(); break;

   }

  }

  void CancelChanges()

  {

   bsStuds.EndEdit();

   bsExams.EndEdit();

   ds.RejectChanges();

  }

}

В режиме дизайна определены такие элементы:

·  BindingNavigator bn, привязанный к данным bsStuds. В него добавлены три кнопки: Save, Cancel Changes и btnReLoad с текстом "Load from DB",

·  SplitContainer, который делит форму на две панели (Horizontal splitter orientation),

·  Дваобъекта DataGridView (gridStuds и gridExams), которые помещены в панели SplitContainer.

Внимание! В этой версии БД колонка даты экзамена имеет имя Date, а не MyDate, потому, что мы теперь знаем, как бороться с проблемами совпадения имен. Надо использовать префиксы и суффиксы. Здесь для них используется символ `, который является родным для СУБД Access (мы говорили об этом ранее).

Внимание! Вам надо добавить метод AddStyle, который вы (или мы) разработали ранее.

При анализе кода главное внимание обратите на метод UpdateDB. Как видите, внесение изменений в базу данных производится постепенно и в том порядке, который мы не раз обсуждали. После добавления строк в таблицу студентов мы даем отдельный запрос SELECT @@IDENTITY, который возвращает новое значение индекса StudID, сгенерированное СУБД. Оно необходимо нам для того, чтобы скорректировать значения связанного ключа в тех строках таблицы экзаменов, которые относятся к текущему студенту. Эту задачу выполняет следующий код.

DataRow[] rows = row.GetChildRows(ds.Relations[0]);

for (int i = 0; i < rows.Length; i++)

   rows[i][1] = id;

Я специально оставил в коде множество отладочных операторов вида:

Debug.WriteLine("Studs added: " + nRows);

В финальном варианте приложения (если вы доведете его до такой стадии) их можно убрать, но в учебных целях желательно оставить. Этот вывод будет виден только в режиме отладки. Повторю избитую истину: окно Output в режиме отладки — это главный учитель программиста. При добавлении строк в таблицу экзаменов также необходимо корректировать индексы первичных ключей. Новые, реальные значения индексов должны попасть в DataSet, иначе будут отказы при удалении этих строк.

Те индексы новых строк, которые вырабатывает ADO.NET, и которые вы видите в обеих компонентах DataGridView (благодаря флагу MissingSchemaAction), не используются при обновлении данных. Они вообще нам не нужны, я оставил их только в учебных целях. В реальном приложении надо убрать эти колонки из DataGridView (но не из DataTable) и не показывать пользователю. Для этого придется изменить алгоритм метода AddStyle и, возможно, подправить код метода HandleEmptyFields.

Метод HandleEmptyFields был добавлен потому, что пользователь может полениться и не ввести значения некоторых полей. В этом случае они будут равны DBNull.Value и их нужно обрабатывать специальным образом. Избежать этой проблемы поможет метод HandleEmptyFields. В нем вы можете дополнить ветви переключателя switch так, чтобы учесть все возможные типы данных.