Украина, Киев |
Методы и свойства объекта DataAdapter. передача изменений в базу данных при помощи объекта Command
Создание объектов SqlCommand для передачи изменений в базу данных
При создании объекта DataAdapter с помощью мастера Data Adapter Configuration Wizard происходит генерирование его структуры. Далее для передачи изменений в базу данных достаточно просто вызвать метод Update - мы только что применяли его в приложении Change_Data. Объект DataAdapter может быть также создан программно при помощи всего двух строк кода. Мы неоднократно делали это для извлечения данных. Однако передача изменений в базу невозможна без определения объектов UpdateCommand, DeleteCommand и InsertCommand. Раскрыв область "Windows Form Designer generated code" в приложении Change_Data, можно обнаружить следующие фрагменты кода:
... this.oleDbDataAdapter1 = new System.Data.OleDb.OleDbDataAdapter(); this.oleDbSelectCommand1 = new System.Data.OleDb.OleDbCommand(); this.oleDbInsertCommand1 = new System.Data.OleDb.OleDbCommand(); this.oleDbUpdateCommand1 = new System.Data.OleDb.OleDbCommand(); this.oleDbDeleteCommand1 = new System.Data.OleDb.OleDbCommand(); ... // // oleDbSelectCommand1 // ... // // oleDbInsertCommand1 // ... // // oleDbUpdateCommand1 // ... // // oleDbDeleteCommand1 // ...
Итак, среда генерирует объекты вместе с соответствующими параметрами. Создайте новое Windows-приложение и назовите его "VisualAllSqlCommands". Перетаскиваем на форму элемент управления Datagrid, его свойству Dock устанавливаем значение "Fill". В окне Toolbox переходим на вкладку Data и добавляем четыре объекта SqlCommand. В свойстве Name каждого из них вводим "mySelectCommand", "myInsertCommand", "myUpdateCommand", "myDeleteCommand". Выделяем объект mySelectCommand в его свойстве Connection выбираем из выпадающего списка значение "New". Появляется окно "Свойства связи с данными", в котором настраиваем подключение к базе данных BDTur_firm2. Завершив настройку, нажимаем кнопку "OK" - на панели компонент появляется объект sqlConnection1. Снова выделяем объект mySelectCommand, в поле его свойства CommandText нажимаем на кнопку (_). В появившемся окне "Query Builder" настраиваем извлечение всех полей таблицы "Туристы". Выделяем объект myInsertCommand и в свойстве Connection выбираем существующее соединение sqlConnection1 (рис. 12.30):
Проделываем то же самое для объектов myUpdateCommand и myDeleteCommand. Снова выделяем объект myInsertCommand, в поле его свойства CommandText нажимаем на кнопку(...). В появившемся окне Query Builder нажимаем кнопку "Close", закрывая дочернее окно Add Table. В поле запроса Query Builder вставляем следующую SQL-конструкцию:
INSERT INTO Туристы (Кодтуриста, Фамилия, Имя, Отчество) VALUES (@Кодтуриста, @Фамилия, @Имя, @Отчество)
Это запрос относится к параметризированным запросам, с ними мы работали в "Подключение к базе данных Microsoft Access" . Нажимаем "OK" для закрытия редактора. Появляется предупреждение: "Для некоторых параметров информация об исходных полях может быть пропущена. Вы действительно хотите применить новую конфигурацию параметров?". Дело в том, что среда пытается получить информацию о параметрах из источника - базы данных, которая не всегда может быть получена. Соглашаемся, однако, с предупреждением, нажимая кнопку "Да" (рис. 12.31):
Для просмотра настроенных параметров в поле свойства "Parameters" нажимаем на кнопку(...). В редакторе SqlParameter Collection Editor можно видеть параметры, свойства которых ( Size, SqlDbType ) совпадают с оригинальными значениями полей базы данных BDTur_firm2 (рис. 12.32):
В этом можно убедиться, запустив SQL Server Enterprise Manager и затем открыв таблицу "Туристы" (рис. 12.33):
Построитель запросов (свойство CommandText ) объекта "myInsert Command" также изменил свой внешний вид - теперь в визуальном режиме можно определять параметры запроса (рис. 12.34):
Перейдем к настройке объекта myUpdateCommand. Выделяем его, в поле свойства CommandText нажимаем кнопку(...). Мы можем снова скопировать и вставить (или ввести вручную) готовую SQL-конструкцию, которая должна быть следующей:
UPDATE Туристы SET Кодтуриста = @Кодтуриста, Фамилия = @Фамилия, Имя = @Имя, Отчество = @Отчество WHERE (Кодтуриста = @Кодтуриста)
После подтверждения окно Query Builder снова изменит свой вид. Если непосредственное написание SQL-запросов вызывает трудности, можно вначале преобразовать вид построителя, а затем воспользоваться визуальным режимом. Для этого после добавления таблицы "Туристы" щелкаем правой кнопкой в поле Query Builder, а затем выбираем пункт меню "Update". Построитель выражений меняет свой внешний вид - далее запрос можно конструировать, отмечая поля таблицы и вводя названия параметров (рис. 12.35):
В любом случае результат будет одинаковым. Выделяем объект myDeleteCommand, в поле свойства CommandText нажимаем кнопку(...). Вводим сразу или конструируем запрос на удаление:
DELETE FROM Туристы WHERE (Кодтуриста = @Кодтуриста) OR (Фамилия = @Фамилия) OR (Имя = @Имя) OR (Отчество = @Отчество)
Здесь мы применяем менее строгий запрос, содержащий оператор OR. Если нужно удалять записи целиком, следует использовать оператор AND:
DELETE FROM Туристы WHERE (Кодтуриста = @Кодтуриста) AND (Фамилия = @Фамилия) AND (Имя = @Имя) AND (Отчество = @Отчество)
В нашем случае значения условий распределяются по столбцам "OR" (рис. 12.36).
Мы завершили настройку объектов Command. В окне Toolbox переходим на вкладку Data и перетаскиваем на форму объект SqlDataAdapter. В появившемся мастере "Data Adapter Configuration Wizard" нажимаем кнопку "Cancel" - у нас уже имеется настроенное подключение. В окне Properties DataAdapter устанавливаем значения свойств "DeleteCommand", "InsertCommand", "SelectCommand" и "UpdateCommand", выбирая из выпадающего списка названия соответствующих объектов (рис. 12.37):
Нажимаем на ссылку "Generate Dataset". В появившемся окне вводим название объекта "dsTourists". Подключаем пространство имен для работы с базой данных:
using System.Data.SqlClient;
В конструкторе формы заполняем объект DataSet и определяем источник данных для элемента DataGrid:
public Form1() { InitializeComponent(); sqlDataAdapter1.Fill(dsTourists1); dataGrid1.DataSource = dsTourists1.Tables[0].DefaultView; }
Изменения будут записываться в базу данных при закрытии формы. Обработчик события Closing формы можно создать в режиме дизайна, нажав на кнопку"Events":
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { sqlDataAdapter1.Update(dsTourists1); }
Этого кода достаточно для сохранения данных, однако приложение будет обращаться к базе данных всякий раз при своем закрытии, даже если изменения внесены не были. Чтобы избежать ненужного расходования трафика, добавим проверку на наличие изменений в объекте DataSet:
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if (dsTourists1.HasChanges()) { sqlDataAdapter1.Update(dsTourists1); } }
Теперь приложение будет соединяться с базой данных только при наличии изменений. Запускаем приложение. Проводя тестирование, вы заметите, что если закрыть форму во время редактирования текущей записи (вызвать метод Update ), внесенные в нее значения сохраняться не будут (рис. 12.38, А). После переключения фокуса ввода, например на новую запись, текущую запись можно сохранить, даже если она содержит не полностью заполненные поля (рис. 12.38, Б).
Рис. 12.38. Готовое приложение "VisualAllSqlCommands". А - закрытие формы при редактировании текущей записи, Б - закрытие формы после переключения фокуса ввода
Эту особенность можно преодолеть, изменив часть приложения, отвечающего за пользовательский интерфейс, например, вводя блокировку завершения работы на время ввода данных6Метод EndCurrentEdit объекта CurrencyManager также позволяет справиться с этой задачей. (см. приложение Change_Data).
В программном обеспечении к курсу вы найдете приложение VisualAll SqlCommands (Code\Glava6 VisualAllSqlCommands).
Сделаем точно такое же приложение, не используя визуальные средства Visual Studio .NET. Создайте новое приложение и назовите его "ProgrammAllSqlCommands". Перетаскиваем на форму элемент управления DataGrid, его свойству Dock устанавливаем значение Fill. Подключаем пространство имен для работы с базой данных:
using System.Data.SqlClient;
В классе формы создаем строку подключения, объекты DataSet и DataAdapter:
string connectionString = "integrated security=SSPI;data source=\".\"; persist security info=False; initial catalog=BDTur_firm2"; DataSet dsTourists; SqlDataAdapter dataAdapter;
В конструкторе формы создаем все объекты ADO .NET:
public Form1() { InitializeComponent(); SqlConnection conn = new SqlConnection(); conn.ConnectionString = connectionString; SqlCommand mySelectCommand = conn.CreateCommand(); mySelectCommand.CommandText = "SELECT * FROM Туристы"; dataAdapter = new SqlDataAdapter(); dataAdapter.SelectCommand = mySelectCommand; dsTourists = new DataSet(); dataAdapter.Fill(dsTourists); dataGrid1.DataSource = dsTourists.Tables[0].DefaultView; //InsertCommand SqlCommand myInsertCommand = conn.CreateCommand(); myInsertCommand.CommandText = "INSERT INTO Туристы (Кодтуриста, Фамилия, Имя, Отчество) VALUES (@Кодтуриста, @Фамилия, @Имя, @Отчество)"; myInsertCommand.Parameters.Add("@Кодтуриста", SqlDbType.Int, 4, "Кодтуриста"); myInsertCommand.Parameters.Add("@Фамилия", SqlDbType.NVarChar, 50, "Фамилия"); myInsertCommand.Parameters.Add("@Имя", SqlDbType.NVarChar, 50, "Имя"); myInsertCommand.Parameters.Add("@Отчество", SqlDbType.NVarChar, 50, "Отчество"); dataAdapter.InsertCommand = myInsertCommand; //UpdateCommand SqlCommand myUpdateCommand = conn.CreateCommand(); myUpdateCommand.CommandText = "UPDATE Туристы SET Кодтуриста = @Кодтуриста, Фамилия = @Фамилия, Имя = @Имя, Отчество = @Отчество WHERE (Кодтуриста = @Кодтуриста)"; myUpdateCommand.Parameters.Add("@Кодтуриста", SqlDbType.Int, 4, "Кодтуриста"); myUpdateCommand.Parameters.Add("@Фамилия", SqlDbType.NVarChar, 50, "Фамилия"); myUpdateCommand.Parameters.Add("@Имя", SqlDbType.NVarChar, 50, "Имя"); myUpdateCommand.Parameters.Add("@Отчество", SqlDbType.NVarChar, 50, "Отчество"); dataAdapter.UpdateCommand = myUpdateCommand; //DeleteCommand SqlCommand myDeleteCommand = conn.CreateCommand(); myDeleteCommand.CommandText = "DELETE FROM Туристы WHERE (Кодтуриста = @Кодтуриста) OR (Фамилия = @Фамилия) OR (Имя = @Имя) OR (Отчество = @Отчество)"; myDeleteCommand.Parameters.Add("@Кодтуриста", SqlDbType.Int, 4, "Кодтуриста"); myDeleteCommand.Parameters.Add("@Фамилия", SqlDbType.NVarChar, 50, "Фамилия"); myDeleteCommand.Parameters.Add("@Имя", SqlDbType.NVarChar, 50, "Имя"); myDeleteCommand.Parameters.Add("@Отчество", SqlDbType.NVarChar, 50, "Отчество"); dataAdapter.DeleteCommand = myDeleteCommand; }
Принципиально нового в этом коде ничего нет - набор Parameters объекта Command мы уже встречали в "Подключение к базе данных Microsoft Access" . В методе Add последним параметром мы передаем значение столбца в объекте DataSet, который будет источником данных для данного параметра (рис. 12.39):
Обработчик события Closing формы будет такой же, как и в предыдущем приложении (с учетом названий объектов):
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if (dsTourists.HasChanges()) { dataAdapter.Update(dsTourists); } }
В программном обеспечении к курсу вы найдете приложение Programm AllSqlCommands (Code\Glava6\ProgrammAllSqlCommands).