Виконання команд над наборами даних

Встановлення з'єднання є необхідною умовою підключення до бази даних. Проте підключення необхідне для того, щоб виконувати певні команди над елементами бази. Розгледимо можливості виконання команд над джерелами даних.

Одним з основних елементів з набору класів ADO.NET, здатним виконувати будь-якого SQL-оператор, є клас Command. Для того, щоб використовувати клас Command, необхідно встановити тип команди, встановити текст запиту SQL і прив'язати її до з'єднання з БД.

Існує 3 типи команд класу Command:

CommandType. Text Виконання прямого оператора SQL, текст якого встановлюється у властивості CommandText. Це значення за умовчанням.
CommandType. StoredProcedure Виконання процедури, що зберігається, ім'я якої встановлене у властивості CommandText.
CommandType. TableDirect Виконання опиту всієї таблиці бази даних, ім'я якої задається у властивості CommandText. Цей тип команди використовується для зворотної сумісності з деякими драйверами OLE DB і не підтримується постачальником даних SQL Server.

Приклад створення об'єкту Command для виконання SQL-запиту і процедури, що зберігається, представлений нижчим.

SqlCommand cmd_SQL = new SqlCommand("Select * From Товари", sqlCon);cmd_SQL.CommandType = CommandType.Text; SqlCommand cmd_Proc=new SqlCommand("GetGoods",sqlCon|);cmd_Proc.CommandType = CommandType.StoredProcedure;

Для виконання створеної команди необхідно використовувати один з наступних методів.

ExecuteReader() Виконання запиту SQL і повернення об'єкту DataReader, що представляє однонаправлений курсор, з доступом тільки для читання.
ExecuteNonQuery() Виконання SQL-команд, призначених для вставки, зміни, видалення записів БД. Результатом роботи команди є кількість рядків, оброблених командою.
ExecuteScalar() Виконання SQL-команды і повернення першого рядка результату запиту. Зазвичай використовується для виконання команди, що містить агрегуючі функції типа COUNT(), MAX() і так далі

При використанні методу ExecuteReader() створюється об'єкт DataReader, за допомогою якого можна організувати перебір всіх рядків поверненого набору даних. Для цього необхідно реалізувати цикл по рядках результуючого набору даних. Об'єкт DataReader є одним з найпростіших і швидших способів діставання доступу до даних БД. У наступному прикладі демонструється спосіб відображення вмісту таблиці "Товари" у вигляді списку.

SqlDataReader rdr_SQL = cmd_SQL.ExecuteReader();StringBuilder strResult=new StringBuilder("");while (rdr_SQL.Read()){ strResult.Append("<li>"); strResult.Append("Код товару <b>"); strResult.Append(rdr_SQL["Кодтовара"]); strResult.Append("</b>, Найменування товару <b>"); strResult.Append(rdr_SQL.GetString(1)); strResult.Append("</b>"); strResult.Append(", Ціна <b>"); strResult.Append(rdr_SQL.GetDouble(2)); strResult.Append("</b></li>");}rdr_SQL.Close();lbl_Result.Text = strResult.ToString();

Звернення до полів таблиці може відбуватися як по імені, так і за допомогою індексу. У випадку з індексом необхідно застосовувати метод, відповідний типові даних того поля, до якого відбувається звернення. Після завершення звернення до даних за допомогою об'єкту DataReader необхідно закрити модуль читання.

У даному прикладі використовується клас StringBuilder, який, як вже демонструвалося раніше, ефективніше працює з рядками. Ті ж самі операції з рядками можливі і із застосуванням стандартної операції конкатенації.

Використаний підхід достатньо трудомісткий для того, щоб його застосовувати на практиці для виведення інформації, що міститься в базі даних. У ASP.NET існує декілька потужніших класів, здатних проводити дану операцію. Одним з таких класів є клас GridView. Застосування даного класу дозволяє здійснювати виведення інформації на екран дуже простим способом. У наступному прикладі показаний спосіб виведення інформації, що отримується з БД за допомогою об'єкту DataReader.

GridView1.DataSource = rdr_SQL;GridView1.DataBind();

Метод ExecuteNonQuery() використовується для виконання команд, які не повертають результуючих наборовши даних. До таких команд відносяться команди вставки, видалення і оновлення даних. Результатом роботи методу ExecuteNonQuery() є кількість оброблених записів. У наступному прикладі демонструється можливість видалення товару з таблиці "Товари".

string strSqlConnection = "Data Source=localhost\\sqlexpress; Initial Catalog=TEST_DB;Integrated Security=SSPI";sqlCon = new SqlConnection(strSqlConnection);SqlCommand cmdDelete = new| SqlCommand("DELETE FROM| Товари WHERE Кодтовара=5",sqlcon);try{ sqlCon.Open(); int n = cmdDelete.ExecuteNonQuery(); lbl_Delete|.Text += String.Format("Видалено {0} записів</br>",n);}catch (SqlException ex|){ lbl_Delete.Text += String.Format("Помилка: {0}</br>" ex.Message);}finally{ sqlCon.Close();}

У реальних ситуаціях практично завжди користувачеві потрібно ввести деяку умову, відповідно до якої виконуватиметься запит SQL. Такою умовою, наприклад, може бути введення найменування товару, підмета видаленню. Для реалізації такої можливості в попередньому прикладі додамо елемент управління TextBox, призначений для введення найменування товару, який необхідно видалити, а також змінимо текст рядка, що формує команду, таким чином:

SqlCommand cmdDelete = new SqlCommand|("DELETE FROM Товари WHERE НазваТовара = '"+tb_delete.Text+"'",sqlCon);

Як видно, в даному випадку, рядок SQL-запроса видалення запису з таблиці "Товари" формується динамічно залежно від введеного в елемент tb_Delete значення. Така практика динамічного формування запитів в реальних застосуваннях допустима, проте при цьому можуть виникати проблеми, пов'язані з безпекою Web-приложения, наприклад атаки впровадженням SQL. Докладніше про такого роду атаках можна прочитати в [1]. Суть цього виду порушення безпеки додатка полягає в тому, що користувач може ввести в поле введення параметра текст, відмінний від того, чого від нього чекає додаток. Це може приводити до того, що текст SQL-запта фактично змінюється і виконує не ту дію, на яку розраховував програміст при його реалізації. Наприклад, якщо в попередньому прикладі в елемент tb_Delete ввести наступний текст "Якийсь товар' OR '1'='1", то в результаті будуть видалені всі записи з таблиці "Товари", оскільки текст SQL-запита в цьому випадку, після підстановки значення введеного в елемент tb_Delete, буде

"DELETE FROM Товари WHERE Назватовара='якийсь товар' OR| '1'='1'"

Як видно з цього прикладу, найменування введеного товару стає неважливим, оскільки умова завжди буде істинною за рахунок додавання оператора OR зі свідомо вірною умовою. Можна навести приклади і складніших атак впровадженням SQL, що приводять до ще серйозніших і масштабніших наслідків і створюють реальну загрозу функціонування всього Web-додатку.

Кращою практикою захисту від атаки впровадженням SQL є використання команд, що параметризуються. Крім того, команди SQL, що параметризуються, простіші при формуванні і застосуванні.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: