Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 9:

Редактирование данных в среде ADO.NET

Редактирование данных средствами DataSet

  • В конце класса Form1 в режиме Code объявите ссылочные переменные как показано ниже, чтобы они были видны во всех будущих методах этого класса
namespace DataEdit
{
  public class Form1 : System.Windows.Forms.Form
  {
..........................................................    
    // Windows Form Designer generated code   
       
    // Переменные-члены класса Form1
    System.Data.DataSet mdsCustIndiv = 
      new System.Data.DataSet();// Объявили и создали набор данных
    System.Data.OleDb.OleDbDataAdapter modaCustIndiv;// Только объявили поставщика
    System.Data.DataRow mdrCustIndiv;// Ссылочная переменная
  }
}
Листинг 9.4. Переменные-члены класса Form1

Задача современного программиста преимущественно сводится к последовательному наращиванию своих классов, которые всю базовую функциональность наследуют от библиотечных классов, хорошо продуманных Большим Биллом и сотоварищами. Мы постепенно компонуем наше приложение из объектов, произведенных от этих классов. Классы здесь выступают как проекты, выполненные Большим Архитектором, а мы должны хорошо разбираться в этих проектах и строить по ним так, чтобы здание стояло и крыша не съехала (ни наша, ни программы). А с нуля ничего стоящего, что можно-бы было продать, сейчас уже не сделаешь - жизни не хватит.

  • Перейдите в режим Design в форме Form1, создайте обработчик события Click для кнопки btnLoadList и заполните его кодом так
private void btnLoadList_Click(object sender, System.EventArgs e)
{
  // Выделить код загрузки в отдельную функцию для возможности
  // многократного использования в этом и других классах
  LoadList();// Наша функция, см.ниже
}
Листинг 9.5. Обработчик события Click для кнопки btnLoadList

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

// Наша функция!!!
// Для загрузки и заполнения всего
private void LoadList()
{
  // Локальные переменные
  System.Data.OleDb.OleDbDataAdapter odaCustList;
  System.Data.DataTable dtCustList = new DataTable();
  System.String strSQL;
  
  // Сформировать строку SQL-запроса закачки в DataTable
  // только полей CustomerID и CompanyName по значению TextBox
  strSQL = "SELECT CustomerID, CompanyName "
    + "FROM Customers WHERE CustomerID LIKE '"
    + txtCustLimit.Text
    + "%'";
  
  // Создать безопасный к исключениям код
  try
  {
    // Создать экземпляр поставщика данных с учетом 
    // значения TextBox, затем заполнить таблицу данных
    odaCustList = new System.Data.OleDb.OleDbDataAdapter(
      strSQL,
      BuildCnnStr("localhost", "Northwind")); // Наша функция, см.ниже
    odaCustList.Fill(dtCustList);
  
    // Связать ListBox с DataTable для отображения данных
    lstCustomers.DataSource = dtCustList;
    lstCustomers.DisplayMember = "CompanyName";
    lstCustomers.ValueMember = "CustomerID";
  
    // Загрузить значения всех полей из поставщика в DataRow,
    // соответствующих строке выделенного элемента списка,
    // затем заполнить значениями все боковые текстовые боксы
    LoadIndividual(); // Наша функция, см.ниже
  }
  catch(System.Data.OleDb.OleDbException oexpData)
  {
    // Объект исключения специализируется на базах данных!!!
    System.Windows.Forms.MessageBox.Show(oexpData.Message);
    return;
  }
}
Листинг 9.6. Код загрузки и заполнения всего

В отдельную функцию для удобства мы выделили формирование строки соединения поставщика с сервером и базой данных

// Наша функция!!! 
// Формирует и возвращает строку параметров для создания
//  соединения поставщика с сервером и базой данных
private string BuildCnnStr(string strServer, string strDatabase)
{
  string strTemp = "Provider=SQLOleDB; Data Source="
    + strServer + ";";
  strTemp += "Initial Catalog=" + strDatabase + ";";
  strTemp += "Integrated Security=SSPI";
  return strTemp;
}
Листинг 9.7. Функция формирования строки соединения поставщика данных

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

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

// Наша функция!!!
// Загружает в набор данных значения полей выделенной в списке записи
// для дальнейшего отображения на экране в текстовых полях TextBox
private void LoadIndividual()
{
  // Очистить набор данных
  mdsCustIndiv.Clear();
  
  // Если строка списка выделена, выбираем данные
  // для заполнения соответствующими значениями текстовых полей
  if(lstCustomers.SelectedIndex == -1) return;
  
  // Создать безопасный к исключениям код
  // для выборки индивидуальных данных
  try
  {
    // Формируем строку SQL-запроса
    System.String strSQL = "SELECT * FROM Customers WHERE CustomerID = '"
      + lstCustomers.SelectedValue // Выбрать все поля записи, 
      + "'"; // значение ключа которой равно выделенному в списке
  
    // Создаем поставщик данных для нужной базы
    modaCustIndiv = new System.Data.OleDb.OleDbDataAdapter(
      strSQL,
      BuildCnnStr("localhost", "Northwind")); // Наша функция, см.выше
  
    // Теперь вместо таблицы наливаем 
    // из поставщика данные в набор данных
    modaCustIndiv.Fill(mdsCustIndiv, "Customers");
  
    // Получить отдельную запись из коллекции строк
    mdrCustIndiv = mdsCustIndiv.Tables["Customers"].Rows[0];
  }
  catch(System.Data.OleDb.OleDbException oexpData)
  {
    System.Windows.Forms.MessageBox.Show(
      "Ошибка в загрузке индивидуальных данных: " + 
      oexpData.Message);
    return;
  }
  
  // Заполнить текстовые поля формы Form1
  // извлеченными значениями данных
  try
  {
    FillTextBox(); // Наша функция, см.ниже
  }
  catch(System.Exception oexp)
  {
    // Если обработчика исключений нет,
    // то все ошибки игнорируются
  }
}
  
// Наша функция!!!
// Заполняет текстовые элементы TextBox 
// значениями полей выбранной пользователем записи
private void FillTextBox()
{
  txtCustomerID.Text = mdrCustIndiv["CustomerID"].ToString();
  txtCompanyName.Text = mdrCustIndiv["CompanyName"].ToString();
  txtContactName.Text = mdrCustIndiv["ContactName"].ToString();
  txtContactTitle.Text = mdrCustIndiv["ContactTitle"].ToString();
  txtAddress.Text = mdrCustIndiv["Address"].ToString();
  
  // Учебное извращение с учетом того, что имена элементов TextBox
  // у нас совпадают с именами полей таблицы Customers + префикс "txt".
  // Хотя от такой сильной связи лучше отказываться - поменяли
  // поля, и все пошло кувырком, и код получается более запутанный
  string tmp = txtCity.Name.ToString().Substring(3);
  txtCity.Text = mdrCustIndiv[tmp].ToString();
  
  tmp = txtRegion.Name.ToString().Substring(3);
  txtRegion.Text = mdrCustIndiv[tmp].ToString();
  
  tmp = txtPostalCode.Name.ToString().Substring(3);
  txtPostalCode.Text = mdrCustIndiv[tmp].ToString();
  
  tmp = txtCountry.Name.ToString().Substring(3);
  txtCountry.Text = mdrCustIndiv[tmp].ToString();
  
  tmp = txtPhone.Name.ToString().Substring(3);
  txtPhone.Text = mdrCustIndiv[tmp].ToString();
  
  tmp = txtFax.Name.ToString().Substring(3);
  txtFax.Text = mdrCustIndiv[tmp].ToString();
}
Листинг 9.8. Найти все поля текущей записи и налить их в элементы TextBox
  • Перейдите в режим Design формы Form1, создайте обработчик события SelectedIndexChanged для списка ListBox и заполните его как показано ниже


// Наша функция!!!
// Меняет содержимое элемента набора данных DataSet
// при каждом выборе пользователем значения списка
private void lstCustomers_SelectedIndexChanged(object sender, System.EventArgs e)
{
  LoadIndividual();
}
Листинг 9.9. Обработчик события выделения строки списка
  • Постройте форму, которая внешне должна выглядеть примерно так


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

Александр Очеретяный
Александр Очеретяный
Украина, Киев
Анастасия Балыбердина
Анастасия Балыбердина
Украина, Киев, НТУУ КПИ