Опубликован: 05.08.2007 | Уровень: специалист | Доступ: платный
Лекция 6:

Свойства и методы объекта Command

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >

Методы 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):

 Выполнение приложения ExampleExecuteNonQuery

Рис. 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Здесь снова "язык DDL языка SQL:" Так уж это принято, ничего не могу с этим поделать. (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):

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

Рис. 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. Мы не будем рассматривать выполнение этих запросов - использование в данном случае объекта Command не отличается ничем от рассмотренного выше.

В программном обеспечении к курсу вы найдете приложение 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):

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

Рис. 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Скорее всего, у вас будет измененное содержимое таблицы "Туры" - если, конечно, вы выполняли все действия, описанные в этой главе. Для получения исходной таблицы запустите SQL Server Enterprise Manager, удалите имеющуюся таблицу "Туры" и импортируйте ее снова из файла BDTur_firm2.mdb ((Code\Glava3\ BDTur_firm2.mdb). - получаем несколько значений из базы данных (рис. 6.18):

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

Рис. 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Таблица "Туристы" была заменена на оригинальную из базы BDTur_firm2.mdb. (рис. 6.19).

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

Рис. 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):

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

Рис. 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):

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

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

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

< Лекция 5 || Лекция 6: 123456 || Лекция 7 >
Александра Тимофеева
Александра Тимофеева
Украина, Киев
Bakke Aleksander
Bakke Aleksander
Россия, Mуниципальный округ N 4