Можно ли отправить коллекцию идентификаторов в качестве параметра ADO.NET SQL?

StackOverflow https://stackoverflow.com/questions/114504

  •  02-07-2019
  •  | 
  •  

Вопрос

Например.могу ли я написать что-то вроде этого кода:

public void InactiveCustomers(IEnumerable<Guid> customerIDs)
{
    //...
    myAdoCommand.CommandText =
        "UPDATE Customer SET Active = 0 WHERE CustomerID in (@CustomerIDs)";
    myAdoCommand.Parameters["@CustomerIDs"].Value = customerIDs;
    //...
}

Единственный известный мне способ — присоединиться к моему IEnumerable, а затем использовать конкатенацию строк для построения строки SQL.

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

Решение

Обычно способ сделать это заключается в передаче списка значений, разделенных запятыми, и внутри вашей хранимой процедуры проанализировать список и вставить его во временную таблицу, которую затем можно использовать для соединений.По состоянию на SQL-сервер 2005, это стандартная практика работы с параметрами, которые должны содержать массивы.

Вот хорошая статья о различных способах решения этой проблемы:

Передача списка/массива в хранимую процедуру SQL Server

Но для SQL-сервер 2008, мы, наконец, сможем передавать табличные переменные в процедуры, сначала определив таблицу как пользовательский тип.

Хорошее описание этого (и других функций 2008 года) есть в этой статье:

Введение в новые возможности программирования T-SQL в SQL Server 2008

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

Вы можете с SQL 2008.Он вышел не так давно, но доступен.

Как было упомянуто в комментарии, Эрланд Соммарског написал серию статей на эту тему (ссылка на них приведена ниже).Статьи очень подробные и могут служить справочным материалом.Хотя некоторые из упомянутых методов специфичны для SQL Server (T-SQL), они также могут работать и для других СУБД (например, использование XML тип данных):

Вы можете использовать тип параметра xml:

CREATE PROCEDURE SelectByIdList(@productIds xml) AS

DECLARE @Products TABLE (ID int) 

INSERT INTO @Products (ID) SELECT ParamValues.ID.value('.','VARCHAR(20)')
FROM @productIds.nodes('/Products/id') as ParamValues(ID) 

SELECT * FROM 
    Products
INNER JOIN 
    @Products p
ON    Products.ProductID = p.ID

http://weblogs.asp.net/jgalloway/archive/2007/02/16/passing-lists-to-sql-server-2005-with-xml-parameters.aspx

Неа.Параметры подобны значениям SQL, подчиняясь первая нормальная форма, по сути, он может быть только один...

Как вы, наверное, знаете, генерация строк SQL — рискованное дело:ты оставляешь себя открытым для SQL-инъекция атаки.Пока вы имеете дело с добросовестными GUID, с вами все будет в порядке, но в противном случае вам нужно обязательно очистить введенные данные.

Вы не можете передать список как один параметр SQl.Вы можете string.Join(',') GUIDS, например "0000-0000-0000-0000, 1111-1111-1111-1111", но это будет сильно нагружать базу данных и на самом деле неоптимально.И вам нужно передать всю строку как один составной динамический оператор, вы не можете добавить ее в качестве параметра.

Вопрос:

Откуда вы берете список идентификаторов неактивных клиентов?

Я предлагаю подойти к проблеме немного по-другому.Переместите всю эту логику в базу данных, например:

    Create procedure usp_DeactivateCustomers 
    @inactive varchar(50) /*or whatever values are required to identify inactive customers*/
    AS    
    UPDATE Customer SET c.Active = 0 
    FROM Customer c JOIN tableB b ON c.CustomerID = b.CustomerID 
    WHERE b.someField = @inactive

И вызовите это как хранимую процедуру:

public void InactiveCustomers(string inactive)
{
    //...
    myAdoCommand.CommandText =
        "usp_DeactivateCustomers";
    myAdoCommand.Parameters["@inactive"].Value = inactive;
    //...
}

Если в базе данных существует список GUID, зачем мне:Найди их;поместите их в общий список;развернуть список в переменную CSV/XML/Table, просто чтобы снова представить их обратно в БД?????Они уже там!Я что-то пропустил?

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