Передача динамического массива SqlParameters в предложение IN строки SQL - PullRequest
0 голосов
/ 06 января 2019

У меня есть способ написать SqlCommand, который включает в себя динамический список параметров. Моя задача - передать каждому из new SqlParameter (@Param0, value0), new sqlParameter (@Param1, value1) ... может быть еще 50 параметров SQL. Его можно передать как жестко запрограммированную строку, но, по понятным причинам, пропуск sb.ToString() не сработает (из-за запятых - это новые аргументы).

Как мне написать цикл или подобное для передачи правильного числа новых аргументов?

Моя попытка на данный момент ниже:

public ViewResult Index(int? ID)
{
    using (var context = new Projects201819Context())
       if (ID == null)
       {
           var sqlCommand = new SqlCommand();

           // Array of item numbers - will change and can be longer/shorter, as required.
           var SQL0 = "SELECT * FROM [database] WHERE material_id IN ({0})";

           var idList = new List<int> { 11, 53, 125};
           int[] idListArray = idList.ToArray();
           var idParameterList = new List<string>();
           var index = 0;
           int IL = idList.Count;

           // Create a SqlParameter for each element in the array called "@idParam0", "@idParam1"... and add to list idParameterList
           foreach (var id in idList)
           {
               var paramName = "@idParam" + index;
               sqlCommand.Parameters.AddWithValue(paramName, id);
               idParameterList.Add(paramName);
               index++;
           }

           // Finalise SQL String for datainput - DONE AND WORKS
           sqlCommand.CommandText = String.Format(SQL0, string.Join(",", idParameterList));

           var newSPList = new List<string>();
           var m = 0;

           foreach (var id in idList)
           {
               var SPName = " new SqlParameter(" + "\"" + "@idParam" + m + "\"" + "," + idListArray[m] + ")";
               newSPList.Add(SPName);
               m++;
           }

           string HELLO = string.Join(",", newSPList);
           string MM = "\"" + sqlCommand.CommandText + "\"" + "," + HELLO;

           var datainput = context.materials.SqlQuery(MM);
           var data = datainput.ToList();

           return View(data);
       }
}

там, где есть идентификатор, хорошо и не дано (остальная часть if (id == null)).

Критическим битом является SPName - он успешно добавляет элементы в список newSPList, а string.join возвращает именно ту строку, которая мне нужна (HELLO), но я не могу затем передать эту длинную строку в качестве отдельных аргументов - имеет смысл - я просто не знаю, как обойти это!

Спасибо за любую поддержку!

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Пусть SQL Server сделает всю грязную работу. Как то так.

var SQL0 = "SELECT * FROM [database] WHERE material_id IN (select value from string_split('{0}',','))";

var idList = new List<int> { 11, 53, 125};
int[] idListArray = idList.ToArray();
sqlCommand.CommandText = String.Format(SQL0, string.Join(",", idListArray));
// now execute the command

EDIT

Более безопасный и эффективный способ.

var SQL0 = "SELECT * FROM [database] WHERE material_id IN (select value from string_split(@ids,','))";

var idList = new List<int> { 11, 53, 125};
int[] idListArray = idList.ToArray();
sqlCommand.CommandText = SQL0;
sqlCommand.Parameters.Add("@ids", SqlDbTypes.VarChar, -1).Value = string.Join(",", idListArray);
// now execute the command
0 голосов
/ 06 января 2019

Вы не можете передать массив параметров таким способом. SqlQuery из EF6 имеет перегрузку , которая принимает в качестве второго параметра массив SqlParameter.

Все, что вам нужно сделать, это:

SqlParameter[] pms = sqlCommand.Parameters.Cast<SqlParameter>().ToArray();
var datainput = context.materials.SqlQuery(sqlCommand.CommandText, pms);

Конечно, это также означает, что большая часть вашего текущего кода не нужна, и вы можете ее удалить

Например, вы можете написать это без объекта SqlCommand, используемого только для хранения параметров и текста команды.

var SQL0 = "SELECT * FROM [database] WHERE material_id IN ({0})";
var idList = new List<int> { 11, 53, 125 };
var idParameterList = new List<string>();
var pms = new List<SqlParameter>();
int count = 1;
foreach (var id in idList)
{
    var paramName = "@idParam" + count++;
    SqlParameter p = new SqlParameter(paramName, SqlDbType.Int);
    p.Value = id;
    pms.Add(p);
    idParameterList.Add(paramName);
}
string cmdText = String.Format(SQL0, string.Join(",", idParameterList));
var datainput = context.materials.SqlQuery(cmdText, pms);
...