Технология Microsoft ADO.NET

       

Методы ExecuteNonQuery, ExecuteScalar и ExecuteReader объекта Command


Мы рассмотрели всю возможную функциональность, которую можно получить без использования каких-либо методов объекта Command. Для выполнения запросов на выборку простейших процедур достаточно просто указать тип и передать название запроса или процедуры. Все работает, но этого явно недостаточно для серьезных приложений. Поэтому забудем пока про хранимые процедуры, другие объекты ADO .NET, и сосредоточим все внимание на методах объекта Command.

Метод ExecuteNonQuery применяется для выполнения запросов, не возвращающих данные. Как же запросы, предназначенные именно для извлечения данных, могут не возвращать их? Речь идет о запросах типа UPDATE, INSERT и DELETE - в самом деле, они вносят изменения в таблицу базы данных, не возвращая ничего назад в результате выполнения. В самом языке SQL эти запросы образуют категорию DML (Data Manipulation Language, DML). Дословный перевод названия категории - "язык манипулирования данными", наличие слова "язык" вносит небольшую путаницу: в языке SQL есть язык DML. Но это именно так. После небольшого опыта подобные названия станут привычными.

Создайте новое консольное приложение и назовите его "Example ExecuteNonQuery". Привожу его полный листинг:

using System; using System.Data.SqlClient;

namespace ExampleExecuteNonQuery { class Class1 { [STAThread] static void Main(string[] args) { SqlConnection conn = new SqlConnection(); conn.ConnectionString = "integrated security=SSPI; data source=\".\"; persist security info=False; initial catalog=BDTur_firm2"; conn.Open(); SqlCommand myCommand = conn.CreateCommand(); myCommand.CommandText = "UPDATE Туристы SET Фамилия = 'Сергеева' WHERE Кодтуриста = 3"; myCommand.ExecuteNonQuery(); conn.Close(); } } }

Объект Command можно создавать, вызывая метод CreateCommand объекта Connection:

SqlCommand myCommand = conn.CreateCommand();

Ранее мы пользовались следующим способом:

SqlCommand myCommand = new SqlCommand(); myCommand.Connection = conn;


Эти два способа совершенно эквивалентны. В свойстве CommandText указывается непосредственно текст запроса, который устанавливает значение "Сергеева" поля "Фамилия" для записи с полем "Кодтуриста" = 3. Для выполнения запроса просто вызываем метод ExecuteNonQuery:

myCommand.ExecuteNonQuery();

Запускаем приложение, нажимая Ctrl+F5. При успешном выполнении запроса в консольном окне появляется надпись "Press any key to continue" (рис. 6.10):


Рис. 6.10.  Выполнение приложения ExampleExecuteNonQuery

Запускаем SQL Server Enterprise Manager, открываем таблицу "Туристы" и убеждаемся в том, что запись изменилась (рис. 6.11).


Рис. 6.11.  Таблица "Туристы", изменение записи

Метод ExecuteNonQuery все-таки что-то неявно возвращает - результат выполнения запроса в виде количества измененных записей; это может применяться для проверки (изменим фрагмент кода):

int UspeshnoeIzmenenie = myCommand.ExecuteNonQuery(); if (UspeshnoeIzmenenie !=0) { Console.WriteLine ("Изменения внесены"); } else { Console.WriteLine("Не удалось внести изменения"); }

Теперь, в зависимости от результата, будет появляться соответствующее сообщение (рис. 6.12).


Рис. 6.12.  Результаты проверки выполнения запроса

Неудачный результат можно получить, установив в тексте запроса значения поля "Код туриста", равное, скажем, 10.

Закомментируем имеющееся свойство CommandText и добавим новое:

myCommand.CommandText = "INSERT INTO Туристы (Кодтуриста, Фамилия, Имя, Отчество) VALUES (6, 'Тихомиров', 'Андрей', 'Борисович')";

Запускаем приложение, переходим в SQL Server Enterprise Manager - запрос добавил новую запись (рис. 6.13):


Рис. 6.13.  Таблица "Туристы", добавление записи

Снова закомментируем свойство CommandText, добавим теперь запрос на удаление записи:

myCommand.CommandText = "DELETE FROM Туристы WHERE Кодтуриста = 4";





Запускаем приложение - из таблицы удалена четвертая запись (рис. 6.14):


Рис. 6.14.  Таблица "Туристы", удаление записи

Метод ExecuteNonQuery применяется также для выполнения запросов, относящихся к категории DDL языка SQL. Язык определения данных3) (Data Definition Language, DDL) позволяет создавать и изменять структуру объектов базы данных, например, создавать и удалять таблицы. Основными операторами этого языка являются CREATE, ALTER, DROP. В результате выполнения запросов DDL не возвращаются данные - именно поэтому мы можем применять метод ExecuteNonQuery. Закомментируем имеющееся свойство CommandText и напишем новое, создающее в базе "BDTur_firm2" новую таблицу "Отзывы":

myCommand.CommandText = "CREATE TABLE Отзывы (Кодотзыва INT NOT NULL, Кодтуриста INT NOT NULL, Комментарий VARCHAR(50)";

Запускаем приложение, затем переходим в SQL Server Enterprise Manager, нажимаем кнопку
(обновить) на панели инструментов - в базе появляется новая таблица (рис. 6.15):


Рис. 6.15.  База данных BDTur_firm2, новая таблица "Отзывы"

Для добавления нового столбца "Отзывтуриста" строка Command Text должна иметь следующий вид:

myCommand.CommandText = "ALTER TABLE Отзывы ADD Отзывтуриста VARCHAR(50)";

В SQL Server Enterprise Manager дважды щелкаем по названию таблицы - в появившемся окне "Table Properties" видим новое поле "Отзывтуриста" (рис. 6.16):


Рис. 6.16.  Свойства таблицы "Отзывы"

Для удаления таблицы "Отзывы" запускаем приложение, содержащее следующую строку CommandText:

myCommand.CommandText = "DROP TABLE Отзывы";

Переходим в SQL Server Enterprise Manager - таблица полностью исчезла из базы данных. Если бы нам нужно было лишь удалить данные из таблицы, сохранив структуру, мы бы воспользовались следующей командой:

myCommand.CommandText = "DELETE FROM Отзывы";

Объектами базы данных могут быть не только таблицы, но и хранимые процедуры, схемы, представления.


В любом случае манипуляция с ними будет относиться к категории DDL.

Метод ExecuteNonQuery применяется для выполнения запросов, относящихся к категории DCL. Язык управления данными (Data Control Language, DCL) предназначен для управления доступом (определения полномочий) к объектам базы данных. Основными операторами этого языка являются GRANT, DENY, REVOKE. Мы не будем рассматривать выполнение этих запросов - использование в данном случае объекта Commnad не отличается ничем от рассмотренного выше.

В программном обеспечении к курсу вы найдете приложение Example ExecuteNonQuery (Code\Glava3\ ExampleExecuteNonQuery).

Метод ExecuteScalar объекта Command применяется для запросов, возвращающих одно значение. Мы сталкивались с такими запросами, когда использовали агрегатные функции COUNT, MIN, MAX. Создайте новое консольное приложение и назовите его "ExampleExecuteScalar". Полный листинг этого приложения:

using System; using System.Data.SqlClient;

namespace ExampleExecuteScalar { class Class1 { [STAThread] static void Main(string[] args) { SqlConnection conn = new SqlConnection(); conn.ConnectionString = "integrated security=SSPI;data source=\".\"; persist security info=False; initial catalog=BDTur_firm2"; conn.Open(); SqlCommand myCommand = conn.CreateCommand(); // SqlCommand myCommand = new SqlCommand(); // myCommand.Connection = conn; myCommand.CommandText = "SELECT COUNT (*) FROM Туры"; string KolichestvoTurov = Convert.ToString(myCommand.ExecuteScalar()); conn.Close(); Console.WriteLine("Количество туров: " + KolichestvoTurov); } } }

Возвращаемый методом ExecuteScalar результат мы привели к типу string для вывода в окно консоли. Запускаем приложение - как и следовало ожидать, запрос вернул число 5 (рис. 6.17):


Рис. 6.17.  Приложение ExampleExecuteScalar, вывод количества туров

Можно несколько раз применять этот метод:

... myCommand.CommandText = "SELECT COUNT (*) FROM Туры"; string KolichestvoTurov = Convert.ToString(myCommand.ExecuteScalar()); myCommand.CommandText = "SELECT MAX (Цена) FROM Туры"; string MaxPrice = Convert.ToString(myCommand.ExecuteScalar()); myCommand.CommandText = "SELECT MIN (Цена) FROM Туры"; string MinPrice = Convert.ToString(myCommand.ExecuteScalar()); myCommand.CommandText = "SELECT AVG (Цена) FROM Туры"; string AvgPrice = Convert.ToString(myCommand.ExecuteScalar()); conn.Close(); Console.WriteLine("Количество туров: " + KolichestvoTurov + "\nСамый дорогой тур, цена в руб. : " + MaxPrice + "\nСамый дешевый тур, цена в руб.: " + MinPrice + "\nСредняя цена туров: " + AvgPrice); }



Запускаем приложение4) - получаем несколько значений из базы данных (рис. 6.18):


Рис. 6.18.  Приложение ExampleExecuteScalar, вывод нескольких значений

Когда требуется получать подобные одиночные значения, всегда следует применять метод ExecuteScalar - это позволяет значительно повысить производительность.

В программном обеспечении к курсу вы найдете приложение Example ExecuteScalar (Code\Glava3\ ExampleExecuteScalar).

Мы переходим к рассмотрению очень важного метода - ExecuteReader. Он применяется для получения набора записей из базы данных. Особенностью этого метода является то, что он возвращает специальный объект DataReader, с помощью которого просматриваются записи. Для хранения данных, полученных из базы, мы до этого использовали объект DataSet. Объект DataReader, в отличие от DataSet, требует наличия постоянного подключения для извлечения и просмотра данных, кроме того, он открывает данные только для чтения. Создайте новое консольное приложение и назовите его "ExampleExecuteReader". Полный листинг этого приложения:

using System; using System.Data.SqlClient;

namespace ExampleExecuteReader { class Class1 { [STAThread] static void Main(string[] args) { SqlConnection conn = new SqlConnection(); conn.ConnectionString = "integrated security=SSPI;data source=\".\"; persist security info=False; initial catalog=BDTur_firm2"; SqlCommand myCommand = conn.CreateCommand(); //SqlCommand myCommand = new SqlCommand(); //myCommand.Connection = conn; myCommand.CommandText = "SELECT * FROM Туристы"; conn.Open(); SqlDataReader dataReader = myCommand.ExecuteReader();

while (dataReader.Read()) { Console.WriteLine(dataReader["Фамилия"]); } dataReader.Close(); conn.Close(); } } }

Объект dataReader создается в результате вызова метода Execute Reader объекта myCommand:

SqlDataReader dataReader = myCommand.ExecuteReader();

Перед считыванием первой записи вызываем метод Read объекта dataReader и выводим набор записей в консольное окно.


Запускаем приложение5) (рис. 6.19).


Рис. 6.19.  Приложение "ExampleExecuteReader". Вывод поля "Фамилия"

Объект DataReader возвращает набор данных типа object, причем для обращения можно использовать индекс:

Console.WriteLine(dataReader[1]);

Это совершенно эквивалентная строка вывода6).

Перечислим несколько полей:

... Console.WriteLine(dataReader[0]); Console.WriteLine(dataReader[1]); Console.WriteLine(dataReader[2]); Console.WriteLine(dataReader[3]); ...

При выводе они будут располагаться в структурированном виде (рис. 6.20):


Рис. 6.20.  Приложение ExampleExecuteReader, вывод содержимого всех полей

Поскольку мы имеем дело с объектами (тип данных object), для вывода записей в виде строк неприменимо их простое объединение:

... Console.WriteLine(dataReader[0] + dataReader[1] + dataReader[2] + dataReader[3]); ...

Преобразованные к типу string значения можно объединять:

Console.WriteLine(Convert.ToString(dataReader[0]) + " "+ Convert.ToString(dataReader[1]) + " "+Convert.ToString(dataReader[2]) + " "+ Convert.ToString(dataReader[3]));

Теперь записи выводятся в более привычном виде (рис. 6.21):


Рис. 6.21.  Приложение ExampleExecuteReader. Вывод содержимого всех полей в виде записей

В программном обеспечении к курсу вы найдете приложение "Example ExecuteReader" (Code\Glava3\ ExampleExecuteReader).


Содержание раздела