
- •А.А. Волосевич
- •4. БАзы данных и технология ado.Net 3
- •4. БАзы данных и технология ado.Net
- •4.1. Архитектура ado.Net
- •4.2. Соединение с базой данных
- •4.3. Выполнение команд и запросов к базе данных
- •4.4. Параметризированные запросы
- •4.5. Чтение данных и объект DataReader
- •4.6. Рассоединенный набор данных
- •4.7. Объект класса DataColumn – колонка таблицы
- •4.8. Объекты класса DataRow – строки таблицы
- •4.9. Работа с объектом класса DataTable
- •4.10. Схема данных и типизированные dataset
- •4.11. Навигация, Поиск и фильтрация данных в DataSet
- •4.12. Класс DataView
- •4.13. Заполнение Рассоединенного набора данных
- •4.14. СиНхронизация набора данных и базы
- •4.15. Работа с транзакциями
4.3. Выполнение команд и запросов к базе данных
Работа с базой данных основана на выполнении запросов. Для выполнения запросов любых типов поставщик данных предоставляет класс, который реализует интерфейс IDbCommand и наследуются от класса DbCommand. В данном параграфе рассматривается класс SqlCommand.
Для создания команды существуют два основных способа. Первый способ – использование конструктора. Класс SqlCommand содержит несколько перегруженных конструкторов: конструктор без параметров; конструктор, которому передается как параметр текст команды; конструктор, принимающий как параметры текст команды и объект-соединение:
var cmd_1 = new SqlCommand();
var cmd_2 = new SqlCommand("SELECT * FROM Albums");
var con = new SqlConnection();
var cmd_3 = new SqlCommand("SELECT * FROM Artists", con);
Второй способ – это создание команды на основе объекта-соединения. В этом случае команда автоматически связывается с соединением.
var con = new SqlConnection();
var cmd = con.CreateCommand();
Связь команды с соединением должна быть установлена перед выполнением команды. В общем случае для этого используется свойство Connection:
var con = new SqlConnection();
var cmd = new SqlCommand { Connection = con };
Свойство команды CommandText содержит текст команды, а свойство CommandType определяет, как следует понимать этот текст. Это свойство может принимать следующие значения:
-
CommandType.Text. Текст команды – это SQL-инструкции. Обычно такие команды передаются в базу без предварительной обработки (за исключением случаев передачи параметров). Этот тип команды устанавливается по умолчанию.
-
CommandType.StoredProcedure. Текст команды – это имя хранимой процедуры, которая находится в базе данных.
-
CommandType.TableDirect. Команда предназначена для извлечения из БД полной таблицы. Имя таблицы указывается в CommandText. Данный тип команд поддерживает только поставщик OLE DB.
Еще одну возможность для настройки команд предоставляет свойство CommandTimeout. Это время в секундах, в течение которого ожидается начало выполнения команды (по умолчанию – 30 секунд). Следует учитывать, что после начала выполнения команды данное свойство никакой роли не играет. Выполнение команды не прервётся, даже если она будет получать данные из базы на протяжении, к примеру, одной минуты.
// пример создания и настройки команды
var con_str = new SqlConnectionStringBuilder
{
DataSource = "(local)",
InitialCatalog = "MusicCatalog",
IntegratedSecurity = true
};
var con = new SqlConnection(con_str.ConnectionString);
var cmd = new SqlCommand
{
Connection = con,
CommandText = "SELECT * FROM Songs",
CommandTimeout = 3,
CommandType = CommandType.Text
};
За подготовкой команды следует её выполнение. Естественно, до выполнения команда должна быть связана с соединением, и это соединение должно быть открыто. В ADO.NET существует несколько способов выполнения команд, которые отличаются лишь информацией, возвращаемой из БД. Ниже перечислены методы выполнения команд, поддерживаемые всеми поставщиками.
-
ExecuteNonQuery(). Этот метод применяется для запросов, не возвращающих данные. Метод возвращает суммарное число строк, добавленных, измененных или удаленных в результате выполнения команды.
-
ExecuteScalar(). Метод выполняет команду и возвращает первый столбец первой строки первого результирующего набора данных. Метод может быть полезен при выполнении запросов или хранимых процедур, возвращающих единственных результат.
-
ExecuteReader(). Этот метод выполняет команду и возвращает объект DbDataReader. Тип возвращаемого ридера соответствует поставщику. Метод ExecuteReader() используется, когда требуется получить набор данных из базы (например, как результат выполнения команды SELECT).
В качестве примера использования метода ExecuteScalar() приведём код, при помощи которого подсчитывается число записей в таблице Songs:
var con = new SqlConnection();
var cmd = new SqlCommand("SELECT COUNT(*) FROM Songs", con);
con.Open();
// приведение типов необходимо, так как метод ExecuteScalar()
// возвращает значение типа object
var count = (int)cmd.ExecuteScalar();
con.Close();
Если в предыдущем примере изменить текст команды на "SELECT * FROM Songs", то в результате выполнения вместо ожидаемого набора данных получим значение первого элемента в первой колонке таблицы Songs.
Поставщик для MS SQL Server поддерживает метод выполнения команды, возвращающий объект класса XmlReader. Это метод ExecuteXmlReader(). Метод поддерживается для SQL Server 2000 и более поздних версий и требует, чтобы возвращаемые данные были в формате XML:
// создали и настроили соединение
var con = new SqlConnection();
// создали и настроили команду
var cmd = new SqlCommand
{
Connection = con,
CommandText = "SELECT * FROM Songs FOR XML AUTO"
};
// выполняем команду
con.Open();
var xml = cmd.ExecuteXmlReader();
// здесь читаем и обрабатываем XML-данные
// внимание: пока это происходит, соединение должно быть открыто
// закрываем соединение
con.Close();
В платформе .NET версии 2.0 у класса SqlCommand был реализован ряд новых методов, позволяющих выполнять асинхронные операции с базой. Для методов ExecuteNonQuery(), ExecuteReader() и ExecuteXmlReader() появились парные асинхронные методы (например, BeginExecuteNonQuery() и EndExecuteNonQuery()). Использование асинхронных команд может быть полезно в тех случаях, когда необходимо выполнение нескольких длительных операций или хранимых процедур. Для применения асинхронных команд необходимо указать в строке соединения параметр «async=true».