是否可以将ID的集合作为ADO.NET SQL参数发送?
例如。我可以写这样的代码:
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值,基本上,只能有一个...
如我们所知,生成SQL字符串是有风险的业务:我们容易遭受SQL注入攻击。只要我们使用的是真正的GUID,就可以了,但是否则,我们必须确保清除输入内容。
我们不能将列表作为单个SQl参数传递。我们可以使用string.Join(',')这样的GUIDS,例如" 0000-0000-0000-0000,1111-1111-1111-1111",但这会增加数据库开销,并且实际上不是最佳选择。而且我们必须将整个字符串作为单个串联的动态语句传递,我们不能将其添加为参数。
问题:
我们从哪里获得代表不活跃客户的ID列表?
我的建议是以不同的方式解决这个问题。将所有逻辑移到数据库中,例如:
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变量,只是将它们再次呈现给数据库?他们已经在那里!我想念什么吗?
通常,执行此操作的方法是传入用逗号分隔的值列表,然后在存储过程中解析该列表并将其插入到临时表中,然后可将其用于联接。从Sql Server 2005开始,这是处理需要保存数组的参数的标准做法。
这是一篇有关解决此问题的各种方法的好文章:
将列表/数组传递给SQL Server存储过程
但是对于Sql Server 2008,我们首先通过将表定义为自定义类型,最终将表变量传递给过程。
本文对此(以及更多2008功能)进行了很好的描述:
SQL Server 2008中新的T-SQL可编程性功能简介
我们可以使用SQL2008. 它还没有发布很长时间,但是已经可以使用。
我们可以使用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