Редактирование данных в среде 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. Обработчик события выделения строки списка
- Постройте форму, которая внешне должна выглядеть примерно так
Убедитесь, что заложенная нами функциональность формы полностью поддерживается.