Ранее для отправки запросов мы напрямую добавляли данные в выражение sql. Например, для отправки запроса на добавление данных в БД применялось следующее выражение:
1 |
string sqlExpression = String.Format("INSERT INTO Users (Name, Age) VALUES ('{0}', {1})", name, age); |
В данном случае предполагается, что значения для переменных name и age вводит пользователь.
Что если переменная name получит следующее значение:
1 |
name = "Tom',10);INSERT INTO Users (Name, Age) VALUES('Hack"; |
В этом случае sql-выражение в итоге будет выглядеть следующим образом:
1 |
INSERT INTO Users (Name, Age) VALUES ('Tom',10);INSERT INTO Users (Name, Age) VALUES('Hack,{1})"; |
В итоге в базу данных будет добавлено два объекта. Это относительно безобидный вид подмены sql-выражения, но реальные возможности встраивания зловредных скриптов таковы, что можно вообще потерять данные в БД, если предоставить пользователям подобным образом добавлять данные.
Чтобы выйти из этой ситуации, в sql-командах используются параметры:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
string connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=usersdb;Integrated Security=True"; int age = 23; string name = "T',10);INSERT INTO Users (Name, Age) VALUES('H"; string sqlExpression = "INSERT INTO Users (Name, Age) VALUES (@name, @age)"; using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = new SqlCommand(sqlExpression, connection); // создаем параметр для имени SqlParameter nameParam = new SqlParameter("@name", name); // добавляем параметр к команде command.Parameters.Add(nameParam); // создаем параметр для возраста SqlParameter ageParam = new SqlParameter("@age", age); // добавляем параметр к команде command.Parameters.Add(ageParam); int number = command.ExecuteNonQuery(); Console.WriteLine("Добавлено объектов: {0}", number); // 1 } |
Для определения параметров используется объект SqlParameter. Этот объект имеет ряд конструкторов, но в данном случае передается название параметра и его значение. Причем название параметров начинается со знака @ и должно совпадать с тем названием, которое используется в sql-выражении (то есть в “INSERT INTO Users (Name, Age) VALUES (@name, @age)”). После определения параметра он добавляется в коллекцию параметров команды.
При выполнении команды на место параметров в sql-выражении подставляются их значения. При этом не важно, что параметр @name в значении определяет еще одну команду INSERT – все его значение будет добавлено в столбец name в таблице Users.