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


