Встановлення з'єднання є необхідною умовою підключення до бази даних. Проте підключення необхідне для того, щоб виконувати певні команди над елементами бази. Розгледимо можливості виконання команд над джерелами даних.
Одним з основних елементів з набору класів ADO.NET, здатним виконувати будь-якого SQL-оператор, є клас Command. Для того, щоб використовувати клас Command, необхідно встановити тип команди, встановити текст запиту SQL і прив'язати її до з'єднання з БД.
Існує 3 типи команд класу Command:
CommandType. Text | Виконання прямого оператора SQL, текст якого встановлюється у властивості CommandText. Це значення за умовчанням. |
CommandType. StoredProcedure | Виконання процедури, що зберігається, ім'я якої встановлене у властивості CommandText. |
CommandType. TableDirect | Виконання опиту всієї таблиці бази даних, ім'я якої задається у властивості CommandText. Цей тип команди використовується для зворотної сумісності з деякими драйверами OLE DB і не підтримується постачальником даних SQL Server. |
Приклад створення об'єкту Command для виконання SQL-запиту і процедури, що зберігається, представлений нижчим.
|
|
Для виконання створеної команди необхідно використовувати один з наступних методів.
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, що параметризуються, простіші при формуванні і застосуванні.