Можно ли отправить коллекцию идентификаторов как параметр ADO.NET SQL? - PullRequest
20 голосов
/ 22 сентября 2008

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

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

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

Ответы [ 6 ]

17 голосов
/ 22 сентября 2008

Как правило, вы делаете это, передавая список значений через запятую, и в рамках вашей хранимой процедуры анализируйте список и вставляйте его во временную таблицу, которую затем можно использовать для объединений. Начиная с Sql Server 2005 , это стандартная практика для работы с параметрами, которые должны содержать массивы.

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

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

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

В этой статье есть хорошее описание этого (и других возможностей 2008 года):

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

5 голосов
/ 22 сентября 2008

Вы можете с SQL 2008 . Это не было очень долго, но это доступно.

2 голосов
/ 29 июня 2015

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

1 голос
/ 22 сентября 2008

Вы можете использовать тип параметра 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

0 голосов
/ 22 сентября 2008

Вы не можете передать список как один параметр SQl. Вы могли бы натянуть .Join (',') ГУИДЫ, такие как "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, просто чтобы снова представить их обратно в БД ????? Они уже там! Я что-то упустил?

0 голосов
/ 22 сентября 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...