Модификация приложения Windows Forms : OLE
Для соединения с базой данных Microsoft Office Access 2003 и ниже (файл *. mdb) в C# следует использовать класс OleDbConnection со следующими параметрами соединения:
Provider=Microsoft.Jet.OLEDB.4.0; Data Source=DataBaseFile
Здесь DataBaseFile — абсолютный путь к файлу базы данных Access. «Провайдер» соединения должен иметь значение Microsoft . Jet . OLEDB .4.0.
Для соединения с базой данных Microsoft Office Access 2007 и выше (файл *.accdb) в C# следует использовать класс OleDbConnection со следующими параметрами соединения:
Provider=Microsoft.ACE.OLEDB.12.0; Data Source=DataBaseFile
Здесь DataBaseFile — абсолютный путь к файлу базы данных Access. «Провайдер» соединения должен иметь значение Microsoft . ACE . OLEDB .12.0 либо для версии Access 2010: Microsoft . ACE . OLEDB .14.0.
Пример:
String ConnetionString = null;
ConnetionStringO = "Provider=Microsoft.ACE.OLEDB.12.0;" +
@"Data Source=D:\Database.accdb";
ConnectionOLE1 = new OleDbConnection(ConnetionStringOLE1);
Для отправки SQL-запросов и чтения их результатов используются объекты OleDbCommand и OleDbDataReader.
Для выполнения запросов на вставку, изменение, или удаление данных из базы данных следует использовать метод класса OleDbCommand: ExecuteNonQuery(). Его вызов выполняет указанный в свойстве CommandText класса OleDbCommand запроc и возвращает int-число затронутых запросом полей.
Пример:
OleDbConnection Conn = new OleDbConnection(@"Provider=Microsoft.ACE.OLEDB.12.0; Data Source=Database.mdb"); // Инициализируем параметры соединения
Conn.Open(); // Открываем соединение с базой даннфх
OleDbCommand Cmd = new OleDbCommand(); // Создаём команду
Cmd.CommandText = "INSERT INTO Main_Table VALUES (1,2,3)"; // Текст команды
|
|
int rowsAffected = Cmd.ExecuteNonQuery(); // Выполнение команды с возвратом в int
System.Windows.Forms.MessageBox.Show(rowsAffected.ToString()); // Вывод результата
Если база данных из примеры выше пустая, то int будет равно единице.
Во время выполнения команд вставки (SQL: INSERT INTO) можно использовать параметры, что может пригодиться, например, для добавления в базу данных файла изображения.
Пример:
OleDbCommand Сmd = new OleDbCommand("INSERT INTO Main_Table (columns) VALUES (@param)", Сonn);
Сmd.Parameters.Add("@param", "abc[[''[]''kl'm");
Сmd.ExecuteNonQuery();
При каких-либо ошибках в синтаксисе, или структуре SQL-запроса, программа падает в OS Loader Lock (фактически прерывается работа), и не дает никакой информации о произошедшей ошибке. Чтобы этого избежать и получить довольно исчерпывающую информацию о произошедшей ошибке, следует выполнять запросы в try-catch блоках. В коде работы подобные приёмы будут использованы повсеместно.
Теперь приступим к формированию второй группы элементов и её функциональности. Для начала расставим элементы как показано на рисунке ниже:
Рис. 4. 1. Расстановка элементов первой группы (OLE # 1)
Здесь представлены три кнопки Button, один ListBox (по центру), простой погашенный TextBox, как в предыдущей группе, и четыре TextBox’а для ввода с клавиатуры данных, которые будут добавлять в базу данных. Слева от каждого размещены по одному текстовому элементу: Label. Также с панели инструментов было добавлен ещё один OpenFileDialog-элемент.
|
|
Функциональность блока будет следующей. При нажатии на кнопку Выбрать базу данных, будет предложено выбрать одну из двух возможных типов базы: это база данных для старых версий Access (*. mdb) и для новых (*. accdb). После этого будет выдано сообщение об успехе или неудаче выбора с описанием причины ошибки в случае неудачи. Далее при нажатии Прочитать все записи, в центральный ListBox будут занесены все записи из базы данных. Ввод значений в TextBox’ы слева и нажатие кнопки Добавить записи сохранит в нашей базе новый записи. Будет использована та же самая база данных, что и для предыдущего блока: LWP 10- DB - ODBC . mdb, а также копия этой же базы, сохранённая как файл *. accdb, для версии Access 2007 или Access 2010. База: LWP 10- DB - OLE . accdb.
По порядку распишем Свойства каждого элемента:
Button:
(Name): | B_OLE_1_Search |
Text: | Выбрать базу данных |
Size: | 200; 23 |
Button:
(Name): | B_OLE_1_Read |
Text: | Прочитать все записи |
Size: | 200; 23 |
Button:
(Name): | B_OLE_1_Add |
Text: | Добавить записи |
Size: | 200; 23 |
TextBox:
|
|
(Name): | TB_OLE_1_Path |
ReadOnly: | True |
ListBox:
(Name): | LB_OLE_1 |
GroupBox:
(Name): | GB_OLE_1 |
Text: | OLE # 1 |
OpenFileDialog:
(Name): | OFD_OLE_1 |
InitialDirectory: | D:\ |
Filter | База данных *.mdb|*.mdb|База данных *.accdb|*.accdb |
TextBox:
(Name): | TB_OLE_1_1 |
TextBox:
(Name): | TB_OLE_1_2 |
TextBox:
(Name): | TB_OLE_1_3 |
TextBox:
(Name): | TB_OLE_1_4 |
Откроем файл LWP 10 Main . cs и в самом начале добавим две ссылки:
using System.Data.OleDb; // OLE
using System.IO; // Для получения расширения файла базы данных
Найдём:
public partial class LWP10Main : Form
{
Double Counter = 4;
OdbcConnection ConnectionOBDC;
Добавим после:
String ConnetionStringOLE1 = null; // Переменная для сохранения данных соединения
OleDbConnection ConnectionOLE1; // Объект для открытия подключения к базе данных
String SQL_OLE = null; // Переменная для поискового запроса
String SQL_OLE_ADD = null; // Переменная для добавления данных
Найдём:
public LWP10Main()
{
InitializeComponent();
TB_ODBC_Path.Text = "D:\\LWP10-DB-ODBC.mdb";
Добавим после:
TB_OLE_1_Path.Text = "D:\\LWP10-DB-OLE.accdb";
B_OLE_1_Read.Enabled = false;
B_OLE_1_Add.Enabled = false;
TB_OLE_1_1.Text = Counter.ToString();
SQL_OLE = "SELECT * FROM [Главная таблица]";
Событие Click кнопки Выбрать базу данных:
private void B_OLE_1_Search_Click(object sender, EventArgs e)
{
if (OFD_OLE_1.ShowDialog() == DialogResult.OK)
|
|
{
B_OLE_1_Read.Enabled = true; // Активируем кнопку "Прочитать все записи"
B_OLE_1_Add.Enabled = true;
//TB_OLE_1_Path.Text = OFD_OLE_1.FileName;
Directory.CreateDirectory(Path.GetDirectoryName(OFD_OLE_1.FileName) + @"\Копии"); // Создаём директорию под изменённые БД
File.Copy(OFD_OLE_1.FileName, Path.GetDirectoryName(OFD_OLE_1.FileName) + @"\Копии\" + OFD_OLE_1.SafeFileName, true); // Копируем туда выбранную БД (перезаписываем, в случае обнаружения похожего файла)
if (Path.GetDirectoryName(OFD_OLE_1.FileName) == Directory.GetDirectoryRoot(OFD_OLE_1.FileName)) // Проверяем путь, если находимся в корневой директории диска, режем один слеш
TB_OLE_1_Path.Text = Path.GetDirectoryName(OFD_OLE_1.FileName) + @"Копии\" + OFD_OLE_1.SafeFileName;
else
TB_OLE_1_Path.Text = Path.GetDirectoryName(OFD_OLE_1.FileName) + @"\Копии\" + OFD_OLE_1.SafeFileName;
if (Path.GetExtension(OFD_OLE_1.FileName) == ".mdb") // Узнаём расширение файла выбранного в диалоге открытия (указываем полный путь) и сравниваем его с ".mdb"
{
ConnetionStringOLE1 = "Provider=Microsoft.Jet.OLEDB.4.0;" +
@"Data Source=" + TB_OLE_1_Path.Text + "";
MessageBox.Show("Выбрана база данных " + TB_OLE_1_Path.Text + " формата: *" + Path.GetExtension(TB_OLE_1_Path.Text) + "!", "Работа с базами данных (C#) :: OLE # 1");
}
if (Path.GetExtension(OFD_OLE_1.FileName) == ".accdb")
{
ConnetionStringOLE1 = "Provider=Microsoft.ACE.OLEDB.12.0;" +
@"Data Source=" + TB_OLE_1_Path.Text + "";
MessageBox.Show("Выбрана база данных " + TB_OLE_1_Path.Text + " формата: *" + Path.GetExtension(TB_OLE_1_Path.Text) + "!", "Работа с базами данных (C#) :: OLE # 1");
}
}
}
Событие Click кнопки Показать все записи:
private void B_OLE_1_Read_Click(object sender, EventArgs e)
{
LB_OLE_1.Items.Clear();
ConnectionOLE1 = new OleDbConnection(ConnetionStringOLE1);
try
{
ConnectionOLE1.Open(); // Открываем соединение
MessageBox.Show("Соединение с базой данных " + TB_OLE_1_Path.Text + " успешно открыто!", "Работа с базами данных (C#) :: OLE # 1");
}
catch (Exception ex) // Ловим исключение и вытаскиваем ошибку через ex.Message
{
MessageBox.Show("Невозможно открыть соединение с базой данных " + TB_OLE_1_Path.Text + " (" + ex.Message + ")!", "Работа с базами данных (C#) :: OLE # 1");
}
OleDbCommand Command = new OleDbCommand(SQL_OLE, ConnectionOLE1); // Формируем SQL-команду для текущего подключения
OleDbDataReader DataReader = Command.ExecuteReader(); // Формируем объект для чтения данных из базы данных
LB_OLE_1.Items.Add(Command.CommandText); // Посылаем текст команды в ListBox
// Организуем циклический перебор полученных записей
while (DataReader.Read())
{
LB_OLE_1.Items.Add(DataReader["Ключевое поле"].ToString() + " | " + DataReader["Первое поле"].ToString() + " | " + DataReader["Второе поле"].ToString() + " | " + DataReader["Третье поле"].ToString());
}
// Закрываем потоки чтения и соединения
DataReader.Close();
ConnectionOLE1.Close();
}
Событие Click кнопки Добавить записи:
private void B_OLE_1_Add_Click(object sender, EventArgs e)
{
LB_OLE_1.Items.Clear(); // Очищаем ListBox перед использованием
ConnectionOLE1 = new OleDbConnection(ConnetionStringOLE1); // Передаём параметры объекту соединения
try
{
ConnectionOLE1.Open(); // Открываем соединение
MessageBox.Show("Соединение с базой данных " + TB_OLE_1_Path.Text + " успешно открыто!", "Работа с базами данных (C#) :: OLE # 1");
}
catch (Exception ex)
{
MessageBox.Show("Невозможно открыть соединение с базой данных " + TB_OLE_1_Path.Text + " (" + ex.Message + ")!", "Работа с базами данных (C#) :: OLE # 1");
}
SQL_OLE_ADD = "INSERT INTO [Главная таблица] VALUES('" + Counter.ToString() + "', '" + this.TB_OLE_1_2.Text + "', '" + this.TB_OLE_1_3.Text + "', '" + this.TB_OLE_1_4.Text + "');";
OleDbCommand Command = new OleDbCommand(SQL_OLE_ADD, ConnectionOLE1);
try
{
Command.ExecuteNonQuery(); // Выполняем команду
}
catch (Exception ex)
{
MessageBox.Show("Невозможно выполнить команду с базой данных " + TB_OLE_1_Path.Text + " (" + ex.Message + ")!", "Работа с базами данных (C#) :: OLE # 1");
}
LB_OLE_1.Items.Add(Command.CommandText); // Отправляем текст команды в ListBox
Counter++;
TB_OLE_1_1.Text = Counter.ToString();
}
Компилируем приложение (Debug) и запускаем:
Рис. 4. 2. Окончательная работа блока: OLE # 1
Предположим, что работа в таком виде с базами данных нас не устраивает. Например, весьма неудобно для базы, где в таблице есть более сотни столбцов, делать эту самую сотню TextBox’ов. В этом случае, когда требуется наглядность данных в приложении и малые трудозатраты лучше нужно использовать элемент управления DataGridView и связанные с ним другие элементы, такие как например DataSet.
Оба элемента можно найти на панели элементов на вкладе Данные.
Собственно DataGridView полезен не только для работы с базами данных. Это просто элемент для предоставления данных в программе (в том числе и в визуальной форме).
Для демонстрации работы с этими элементами организуем третью группу элементов: OLE # 2. Приложение же будет выполнять тот же запрос, что и в предыдущем примере, но будет помещать результат в объект DataSet, который подключается к элементу управления DataGridView, а тот автоматически отображает все данные. Для сохранения данных в базе будет использоваться метод «двухсторонней привязки3 данных», который позволит не только просматривать открывшуюся таблицу, но и вводить изменения в элемент DataGridView, добавляя новые строки, изменяя содержимое имеющихся строк и удаляя ненужные. Объекты класса DataAdapter способны выполнять как операцию SELECT, получая данные запроса из базы данных, так и команды INSERT, UPDATE и DELETE, изменяя содержимое таблицы базы данных.
Но прописывать данные команды самостоятельно надобности нет. Пространство имен System.Data содержит небольшой, но очень полезный класс CommandBuilder, который умеет создавать команды SQL и автоматически их выполнять.
ПРИМЕЧАНИЕ № 3: Подключение источника данных к визуальному элементу управления называется привязкой, или связыванием данных.
Теперь приступим к формированию третьей группы элементов и её функциональности. Для начала расставим элементы как показано на рисунке ниже:
Рис. 4. 3. Расстановка элементов первой группы (OLE # 2)
Здесь представлены три кнопки Button, один, простой погашенный TextBox, как в предыдущей группе и два DataGridView. Также с панели инструментов было добавлен ещё один OpenFileDialog-элемент и один DataSet. Сразу оговоримся, для работы с добавлением данных через DataGridView база данных была переделана и название таблиц и столбцов были изменены (убраны символы кириллицы). Это связано с тем, что при работе с базой, в которой есть не английские символы в названиях таблиц (и столбцов) можно столкнуться с ошибками (не всегда). Сама же база осталась без изменений, Название: LWP 10- DB - OLE - Special . accdb. Содержание таблицы Main _ Table:
Функциональность блока будет следующей. Выбираем базу данных как в предыдущих случаях и жмём на Показать все записи. Всплывающее сообщение с результатами, за которым идёт добавление всех данных базы в левый (по рисунку 4. 3) DataGridView. Правый же будет загружен сразу при старте приложения (база будет взята по статическому пути D :\ LWP 10- DB - Special . accdb. Вносим изменения в ячейки (в правом DataGridViewv) и жмём на Сохранить записи. Результат можно будет увидеть перезагрузив приложение, либо открыв базу через Access. Изменения ячеек в левом DataGridView не будут нигде сохранены.
По порядку распишем Свойства каждого элемента:
Button:
(Name): | B_OLE_2_Search |
Text: | Выбрать базу данных |
Size: | 200; 23 |
Button:
(Name): | B_OLE_2_Read |
Text: | Прочитать все записи |
Size: | 200; 23 |
Button:
(Name): | B_OLE_2_Save |
Text: | Сохранить записи |
Size: | 200; 23 |
TextBox:
(Name): | TB_OLE_2_Path |
ReadOnly: | True |
GroupBox:
(Name): | GB_OLE_2 |
Text: | OLE # 2 |
OpenFileDialog:
(Name): | OFD_OLE_2 |
InitialDirectory: | D:\ |
Filter | База данных *.mdb|*.mdb|База данных *.accdb|*.accdb |
DataGridView:
(Name): | DataGridViewOLE |
DataGridView:
(Name): | DataGridViewOLE_S |
DataSetw:
(Name): | DataSetOLE |
Теперь перейдём к коду. Найдём:
String SQL_OLE_ADD = null; // Переменная для добавления данных
Добавим после:
String ConnetionStringOLE2 = null;
OleDbConnection ConnectionOLE2;
String ConnetionStringOLE_S = null;
OleDbConnection ConnectionOLE_S;
OleDbDataAdapter DataAdapter_S;
Найдём:
SQL_OLE = "SELECT * FROM [Главная таблица]";
Добавим после:
TB_OLE_2_Path.Text = "D:\\LWP10-DB-OLE.accdb";
B_OLE_2_Read.Enabled = false;
DataGridViewOLE.DataMember = "Table"; // Указываем на тип подсписка для DataGridView
Событие Click кнопка Выбор базы данных:
private void B_OLE_2_Search_Click(object sender, EventArgs e)
{
if (OFD_OLE_2.ShowDialog() == DialogResult.OK)
{
B_OLE_2_Read.Enabled = true;
B_OLE_2_Save.Enabled = true;
//TB_OLE_2_Path.Text = OFD_OLE_2.FileName;
Directory.CreateDirectory(Path.GetDirectoryName(OFD_OLE_2.FileName) + @"\Копии"); // Создаём директорию под изменённые БД
File.Copy(OFD_OLE_2.FileName, Path.GetDirectoryName(OFD_OLE_2.FileName) + @"\Копии\" + OFD_OLE_2.SafeFileName, true); // Копируем туда выбранную БД (перезаписываем, в случае обнаружения похожего файла)
if (Path.GetDirectoryName(OFD_OLE_2.FileName) == Directory.GetDirectoryRoot(OFD_OLE_2.FileName)) // Проверяем путь, если находимся в корневой директории диска, режем один слеш
TB_OLE_2_Path.Text = Path.GetDirectoryName(OFD_OLE_2.FileName) + @"Копии\" + OFD_OLE_2.SafeFileName;
else
TB_OLE_2_Path.Text = Path.GetDirectoryName(OFD_OLE_2.FileName) + @"\Копии\" + OFD_OLE_2.SafeFileName;
if (Path.GetExtension(OFD_OLE_2.FileName) == ".mdb")
{
ConnetionStringOLE2 = "Provider=Microsoft.Jet.OLEDB.4.0;" +
@"Data Source=" + TB_OLE_2_Path.Text + "";
MessageBox.Show("Выбрана база данных " + TB_OLE_2_Path.Text + " формата: *" + Path.GetExtension(TB_OLE_2_Path.Text) + "!", "Работа с базами данных (C#) :: OLE # 2");
}
if (Path.GetExtension(OFD_OLE_2.FileName) == ".accdb")
{
ConnetionStringOLE2 = "Provider=Microsoft.ACE.OLEDB.12.0;" +
@"Data Source=" + TB_OLE_2_Path.Text + "";
MessageBox.Show("Выбрана база данных " + TB_OLE_2_Path.Text + " формата: *" + Path.GetExtension(TB_OLE_2_Path.Text) + "!", "Работа с базами данных (C#) :: OLE # 2");
}
}
}
Событие Click кнопка Показать все записи:
private void B_OLE_2_Read_Click(object sender, EventArgs e)
{
DataSetOLE.Clear(); // Очищаем DataSetOLE перед повторным заполнением из базы данных
ConnectionOLE2 = new OleDbConnection(ConnetionStringOLE2);
try
{
ConnectionOLE2.Open(); // Открываем соединение
MessageBox.Show("Соединение с базой данных " + TB_OLE_2_Path.Text + " успешно открыто!", "Работа с базами данных (C#) :: OLE # 2");
}
catch (Exception ex)
{
MessageBox.Show("Невозможно открыть соединение с базой данных " + TB_OLE_2_Path.Text + " (" + ex.Message + ")!", "Работа с базами данных (C#) :: OLE # 2");
}
// Создаем объект DataAdapter и передаём ему данные запроса
OleDbDataAdapter DataAdapter = new OleDbDataAdapter(); // DataAdapter - посредник между базой данных и DataSet
DataAdapter.SelectCommand = new OleDbCommand(SQL_OLE, ConnectionOLE2);
DataAdapter.Fill(DataSetOLE); // Данные из адаптера поступают в DataSet
DataGridViewOLE.DataSource = DataSetOLE; // Связываем данные с элементом DataGridView
// Закрываем соединение
ConnectionOLE2.Close();
}
Событие Click кнопка Сохранить записи:
private void B_OLE_2_Save_Click(object sender, EventArgs e)
{
try
{
DataAdapter_S.Update((DataTable)DataGridViewOLE_S.DataSource);
MessageBox.Show("Изменения в базе данных D:\\Копии\\LWP10-DB-OLE-Special.accdb успешно внесены!", "Работа с базами данных (C#) :: OLE # 2");
}
catch (Exception ex)
{
MessageBox.Show("Невозможно сохранить изменения в базе данных D:\\Копии\\LWP10-DB-OLE-Special.accdb (" + ex.Message + ")!", "Работа с базами данных (C#) :: OLE # 2");
}
}
Событие Load формы:
private void LWP10Main_Load(object sender, EventArgs e)
{
Directory.CreateDirectory(@"D:\" + @"\Копии");
File.Copy(@"D:\LWP10-DB-OLE-Special.accdb", @"D:\" + @"\Копии\" + @"LWP10-DB-OLE-Special.accdb", true);
ConnetionStringOLE_S = "Provider=Microsoft.ACE.OLEDB.12.0;" +
@"Data Source=D:\Копии\LWP10-DB-OLE-Special.accdb";
ConnectionOLE_S = new OleDbConnection(ConnetionStringOLE_S);
try
{
ConnectionOLE_S.Open(); // Открываем соединение
MessageBox.Show("Соединение с базой данных D:\\Копии\\LWP10-DB-OLE-Special.accdb успешно открыто!", "Работа с базами данных (C#) :: OLE # 2");
}
catch (Exception ex)
{
MessageBox.Show("Невозможно открыть соединение с базой данных D:\\Копии\\LWP10-DB-OLE-Special.accdb (" + ex.Message + ")!", "Работа с базами данных (C#) :: OLE # 2");
}
DataTable DataTable_S = new DataTable();
// Создаём команду
OleDbCommand Command = new OleDbCommand("SELECT * FROM Main_Table", ConnectionOLE_S);
// Создаём адаптер DataAdapter_S: посредник между базой данных и DataSet
DataAdapter_S = new OleDbDataAdapter(Command);
// Создаём построитель команд
// Для адаптера становится доступной команда Update и другие команды
OleDbCommandBuilder CommandBuilder = new OleDbCommandBuilder(DataAdapter_S);
// Данные из адаптера поступают в DataTable_S
DataAdapter_S.Fill(DataTable_S);
// Связываем данные с элементом DataGridView
DataGridViewOLE_S.DataSource = DataTable_S;
// Закрываем соединение
ConnectionOLE_S.Close();
}
Компилируем приложение (Debug) и запускаем:
Рис. 4. 4. Окончательная работа блока: OLE # 2
Дата добавления: 2019-09-13; просмотров: 205; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!