在C#中的SQL查询中将字符串数组作为参数传递

use*_*679 2 c# sql-server sqlcommand sqlcommandbuilder

在我用C#编写的应用程序中,我正在编写一个SQL查询.以下是查询

SELECT [Resource No_] where [Resource No_] In (@resources) 
Run Code Online (Sandbox Code Playgroud)

@resources 是具有一个或多个一个字符串的用户输入参数.

我的查询失败而没有显示错误

根据我的说法,查询失败,因为@resources正在传递参数跟随

"'123,'124','125'"
Run Code Online (Sandbox Code Playgroud)

(在开头和结尾两个引号,这是我的查询失败).

[Resource No_]NVARCHAR数据库中的类型.

谷歌搜索后,我已经找到了一些关于这个主题的帮助,但所有这些都适用[Resource No_] 于类型Integer

use*_*740 5

虽然我不同意"重复问题"的选定答案(或许多棘手的答案),但这里是一个答案,它显示了与我的以下建议非常相似的方法.

(我已经投票决定关闭这个问题作为一个重复,因为如果这样埋答案,甚至.)


只能将一个SQL值绑定到任何给定的占位符.

虽然有办法将所有数据作为"一个值"发送,但我建议动态创建占位符:它简单,干净,并且在大多数情况下都能可靠地工作.

考虑一下:

ICollection<string> resources = GetResources();

if (!resources.Any()) {
    // "[Resource No_] IN ()" doesn't make sense
    throw new Exception("Whoops, have to use different query!");
}

// If there is 1 resource, the result would be "@res0" ..
// If there were 3 resources, the result would be "@res0,@res1,@res2" .. etc
var resourceParams = string.Join(",",
    resources.Select((r, i) => "@res" + i));

// This is NOT vulnerable to classic SQL Injection because resourceParams
// does NOT contain user data; only the parameter names.
// However, a large number of items in resources could result in degenerate
// or "too many parameter" queries so limit guards should be used.
var sql = string.Format("SELECT [Resource No_] where [Resource No_] In ({0})",
    resourceParams);

var cmd = conn.CreateCommand();
cmd.CommandText = sql;

// Assign values to placeholders, using the same naming scheme.
// Parameters prevent SQL Injection (accidental or malicious).
int i = 0;
foreach (var r in resources) {
   cmd.Parameters.AddWithValue("@res" + i, r);
   i++;
}
Run Code Online (Sandbox Code Playgroud)