Я использую C# и .NET 3.5. Мне нужно сгенерировать и сохранить некоторые операторы вставки T-SQL, которые будут выполняться позже на удаленном сервере.
Например, у меня есть массив сотрудников:
new Employee[]
{
new Employee { ID = 5, Name = "Frank Grimes" },
new Employee { ID = 6, Name = "Tim O'Reilly" }
}
и мне нужно получить массив строк, например:
"INSERT INTO Employees (id, name) VALUES (5, 'Frank Grimes')",
"INSERT INTO Employees (id, name) VALUES (6, 'Tim O''Reilly')"
Я смотрю на код, который создает операторы вставки с помощью String.Format, но мне кажется, что это неправильно. Я рассматривал возможность использования SqlCommand (надеясь сделать что-то вроде этого), но он не предлагает способа комбинировать текст команды с параметрами.
Достаточно ли просто заменить одинарные кавычки и построить строку?
string.Format("INSERT INTO Employees (id, name) VALUES ({0}, '{1}')",
employee.ID,
replaceQuotes(employee.Name)
);
О чем я должен беспокоиться при этом? Исходные данные достаточно безопасны, но я не хочу делать слишком много предположений.
Обновлено: просто хочу указать, что в этом случае у меня нет SqlConnection или какого-либо способа напрямую подключиться к SQL Server. Это конкретное приложение должно генерировать операторы sql и ставить их в очередь для выполнения в другом месте - в противном случае я бы использовал SqlCommand.Parameters.AddWithValue ()





Используйте параметризованные команды. Также передайте параметры вашему удаленному серверу и заставьте его вызывать SQL Server, сохраняя при этом различие между самим SQL и значениями параметров.
Если вы никогда не смешиваете данные как код, все должно быть в порядке.
На самом деле, сейчас просто ложусь спать. Проповедь завтра утром с 10.30 до 11.30, так что тогда вам гарантирован хороший удар кнутом! ;)
Проповедовать? Есть записи?
@tofutim: Я не знаю.
Кажется, это не дает решения, когда жесткое требование, чтобы на выходе был файл сценария .sql с готовыми командами INSERT с данными, которые нужно вставить.
@ O.R.Mapper: Действительно - обратите внимание, что OP добавил это требование после того, как я ответил, хотя они все же приняли мой ответ, как ни странно ...
@JonSkeet: Верно - вероятно, подходит для OP, но несколько раздражает будущих посетителей, которые действительно сталкиваются с проблемой, как описано в вопросе.
Создайте свой объект SqlCommand следующим образом:
SqlCommand cmd = new SqlCommand(
"INSERT INTO Employees (id, name) VALUES (@id, @name)", conn);
SqlParameter param = new SqlParameter();
param.ParameterName = "@id";
param.Value = employee.ID;
cmd.Parameters.Add(param);
param = new SqlParameter();
param.ParameterName = "@name";
param.Value = employee.Name;
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
Использование "cmd.AddWithValue (" @ id ", employee.ID);" намного короче.
Я получаю это время от времени и получил это в своем ответе на этот.
Брэд Уилсон: Требуются дополнительные параметры: cmd.Parameters.AddWithValue("@id", employee.ID);.
Как это отвечает на вопрос? OP четко заявляет, что у них нет доступа к БД, и вместо этого им нужно выводить команды, которые можно запустить позже.
Чтобы избежать внедрения, вам необходимо отправить данные на удаленный сервер (возможно, в XML), а затем на удаленный сервер данные должны быть преобразованы обратно в соответствующие типы данных и использоваться в параметризованных запросах или сохраненных процессах.
Хм, я согласен со всеми, что вы должны использовать параметризованные запросы, и оставим все как есть. Но как вы собираетесь передавать эти SQL-запросы на удаленный сервер? Есть ли у вас какой-либо тип службы, такой как веб-служба, которая будет принимать и выполнять произвольные команды Sql, или ваше клиентское приложение будет напрямую обращаться к БД?
Если вы используете какой-то прокси-сервер, то независимо от того, насколько вы дезинфицируете свои данные на клиенте, хакер может просто обойти ваше приложение и обратиться к сервису. В этом случае сделайте то, что рекомендует Cade, и передайте данные, например, как XML или в любом другом формате, который вы выберете (JSON, двоичный и т. д.). Затем создайте свой SQL прямо перед тем, как вы действительно запустите команду.
Исправьте функцию замены кавычек следующим образом:
void string replaceQuotes(string value) {
string tmp = value;
tmp = tmp.Replace("'", "''");
return tmp;
}
Ваше здоровье!
Гораздо проще использовать параметры, подумайте обо всех символах, которые нужно экранировать. Кроме того, это не безопасно для SQL-инъекций.
@ KarelFrajták: Как можно использовать параметры, если отформатированные команды будут выполняться только позже (предположительно, после завершения выполнения кода C#), как описано в вопросе?
@ O.R.Mapper, в этом случае я бы поставил в очередь операторы и словарь с именами и значениями параметров.
AddWithValue великолепен (я часто использую его), НО он может страдать от неправильного неявного преобразования типов, если не использовать его осторожно.