Вопрос

Параметризованные запросы в .Net всегда выглядят так в примерах:

SqlCommand comm = new SqlCommand(@"
   SELECT * 
   FROM   Products 
   WHERE  Category_ID = @categoryid
", 
   conn);
comm.Parameters.Add("@categoryid", SqlDbType.Int);
comm.Parameters["@categoryid"].Value = CategoryID;

Но я натыкаюсь на кирпичную стену, пытаясь сделать следующее:

SqlCommand comm = new SqlCommand(@"
   SELECT * 
   FROM   Products 
   WHERE  Category_ID IN (@categoryids) 
      OR  name LIKE '%@name%'
", 
   conn);
comm.Parameters.Add("@categoryids", SqlDbType.Int);
comm.Parameters["@categoryids"].Value = CategoryIDs;
comm.Parameters.Add("@name", SqlDbType.Int);
comm.Parameters["@name"].Value = Name;

Где

  • CategoryIDs - это разделенный запятыми список чисел "123 456 789" (без кавычек).
  • Name - это строка, возможно, с одинарными кавычками и другими неправильными символами

Каков правильный синтаксис для этого?

Это было полезно?

Решение

Допустим, у вас есть идентификаторы вашей категории в целочисленном массиве, а Name - это строка.Хитрость заключается в создании текста команды, позволяющего вам вводить все идентификаторы вашей категории в качестве отдельных параметров и создавать нечеткое соответствие имени.Чтобы выполнить первое, мы используем цикл для построения последовательности имен параметров с @p0 по @pN-1, где N - количество идентификаторов категорий в массиве.Затем мы создаем параметр и добавляем его в команду с соответствующим идентификатором категории в качестве значения для каждого именованного параметра.Затем мы используем конкатенацию по имени в самом запросе, чтобы разрешить нечеткий поиск по имени.

string Name = "someone";
int[] categoryIDs = new int[] { 238, 1138, 1615, 1616, 1617,
                                1618, 1619, 1620, 1951, 1952,
                                1953, 1954, 1955, 1972, 2022 };

SqlCommand comm = conn.CreateCommand();

string[] parameters = new string[categoryIDs.Length];
for(int i=0;i<categoryIDs.Length;i++)
{
   parameters[i] = "@p"+i;
   comm.Parameters.AddWithValue(parameters[i], categoryIDs[i]);
}
comm.Parameters.AddWithValue("@name",$"%{Name}%");
comm.CommandText = "SELECT * FROM Products WHERE Category_ID IN (";
comm.CommandText += string.Join(",", parameters) + ")";
comm.CommandText += " OR name LIKE @name";

Это полностью параметризованный запрос, который должен порадовать вашего администратора базы данных.Я подозреваю, что, поскольку это целые числа, хотя просто создать текст команды непосредственно со значениями, сохраняя при этом параметризацию имени, не представляло бы большого риска для безопасности.Если ваши идентификаторы категорий находятся в строковом массиве, просто разделите массив на запятые, преобразуйте каждый из них в целое число и сохраните его в целочисленном массиве.

Примечание: Я говорю array и использую его в примере, но он должен работать для любой коллекции, хотя ваша итерация, вероятно, будет отличаться.

Оригинальная идея от http://www.tek-tips.com/viewthread.cfm?qid=1502614&page=9

Другие советы

Вам нужно "%" в значении параметра sql.

SqlCommand comm = new SqlCommand("SELECT * FROM Products WHERE Category_ID IN (@categoryid1, @categoryid2) OR name LIKE @name", conn);
comm.Parameters.Add("@categoryid1", SqlDbType.Int);
comm.Parameters["@categoryid1"].Value = CategoryID[0];
comm.Parameters.Add("@categoryid2", SqlDbType.Int);
comm.Parameters["@categoryid2"].Value = CategoryID[1];
comm.Parameters.Add("@name", SqlDbType.Int);
comm.Parameters["@name"].Value = "%" + Name + "%";

Такой подход не сработает.Точка.

Предложение IN ожидает сам список параметров, поэтому, когда вы привязываете один параметр к нему, у вас есть возможность передать в один ценность.

Создайте свою строку оператора динамически, с точным количеством отдельных заполнителей предложения IN, которые вы собираетесь передать, а затем добавьте параметры и привяжите к ним значения в цикле.

не уверен, что это правильный путь, но именно так я делал это раньше

список templist = новый список

связь.Параметры.Добавить("@categoryids", SqlDbType.varchar);связь.Параметры["@categoryids"].значение = string.join(",",templist.toarray())

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top