C# 如何使用列表<;int>;作为C中的SQL参数#

C# 如何使用列表<;int>;作为C中的SQL参数#,c#,.net,sql,C#,.net,Sql,我试图使用以下代码将列表用作SQL参数: var listID= new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; using (var sqlConnection = new SqlConnection(_connectionstring)) { using (var cmd = new SqlCommand()) { cmd

我试图使用以下代码将
列表
用作SQL参数:

var listID= new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

        using (var sqlConnection = new SqlConnection(_connectionstring))
        {
            using (var cmd = new SqlCommand())
            {
                cmd.Connection = sqlConnection;
                cmd.CommandText = "delete from MyTable where TableID in ( @tableID)";

                string param = String.Join(",", listID.ToArray());
                cmd.Parameters.Add("@tableID", param);
                sqlConnection.Open();
                cmd.ExecuteNonQuery();
            }
            sqlConnection.Close();
        }
var listID=newlist(){1,2,3,4,5,6,7,8,9};
使用(var sqlConnection=newsqlconnection(_connectionstring))
{
使用(var cmd=new SqlCommand())
{
cmd.Connection=sqlConnection;
cmd.CommandText=“从MyTable中删除,其中TableID位于(@TableID)”;
string param=string.Join(“,”,listID.ToArray());
cmd.Parameters.Add(“@tableID”,param);
sqlConnection.Open();
cmd.ExecuteNonQuery();
}
sqlConnection.Close();
}
问题是,此代码将生成:

exec sp_executesql N'delete from MyTable where TableID in( @tableID'),N'@tableID nvarchar(17)”,@tableID=N'1,2,3,4,5,6,7,8,9'

这将失败,因为:

转换nvarchar值时转换失败 “1,2,3,4,5,6,7,8,9”转换为数据类型int

你知道怎么解决这个问题吗?多谢各位


编辑:我在SQL Server 2008及更高版本中使用MS SQL 2012,您可以使用表值参数。因为它们只是一个逗号分隔的整数,所以我还将尝试在存储过程中保留delete语句,并传递xml字符串或原样传递,以便解析为表变量。这在很多方面都是可行的,正如其他答案中所提到的,表值参数似乎是干净的。

我通常会使用某种ORM,但如果您想继续使用类似于现有的ORM,您可以尝试以下方法:

    var listID= new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    using (var sqlConnection = new SqlConnection(_connectionstring))
    {
        using (var cmd = new SqlCommand())
        {
            cmd.Connection = sqlConnection;
            cmd.CommandText = "delete from MyTable where TableID in (" + String.Join(",",listID) + ")";
            sqlConnection.Open();
            cmd.ExecuteNonQuery();
        }
        sqlConnection.Close();
    }
var listID=newlist(){1,2,3,4,5,6,7,8,9};
使用(var sqlConnection=newsqlconnection(_connectionstring))
{
使用(var cmd=new SqlCommand())
{
cmd.Connection=sqlConnection;
cmd.CommandText=“从MyTable中删除,其中TableID位于(“+String.Join”(“,”,listID)+”)中”;
sqlConnection.Open();
cmd.ExecuteNonQuery();
}
sqlConnection.Close();
}
您应该使用,这样您就可以完全按照指定的方式保留查询。它们是在SQL 2008中引入的


在SQLServer2005中,我编写了一个CLR函数,将逗号分隔的列表转换为一组nvarchar

[SqlFunction(DataAccess = DataAccessKind.None,
                IsDeterministic = true,
                SystemDataAccess = SystemDataAccesskind.None,
                IsPrecise = true,
                FillRowMethodName = "SplitFillRow",
                TableDefinition = "s NVARCHAR(MAX)")]
public static IEnumerable Split(SqlChars seperator, SqlString s)
{
    if (s.IsNull)
    {
        return new string[0];
    }

    return s.ToString().Split(seperator.Buffer);
}

public static void SplitFillRow(object row, out SqlString s)
{
    s = new SqlString(row.ToString());
}
我认为这是一种有效使用.Net CLR的方法,并且优于非CLR的替代方法



在SQL Server 2008+中,您可以使用。

是SQL Server吗,如果是,是什么版本?是的,对不起,是SQL Server 2012。我将扩展我的问题。多个参数(用逗号分隔)和一个恰好包含逗号的字符串参数之间存在逻辑差异。T-SQL(和其他所有sane语言一样)不会尝试拆分单个参数。您确定中的
将使用一个参数吗?(我的意思是:一对一,而不是一对一…)检查这个问题:stackoverflow.com/questions/182060/where-in-array-of-ids为什么被否决?考虑到这个问题,这似乎是合理的。如果您使用动态SQL,它的效果会令人惊讶。@MichaelTodd我猜,因为即使它在当前形式下是安全的,但细微的修改(
List
)会使它变得非常不安全。就个人而言,我并不一定反对动态SQL,但如果需要使用动态SQL,一个通常更好的选择可能是在(@p0,@p1,@p2,…)中构建一个
where TableID
查询并将列表值存储在参数中。@hvd我知道SQL注入,但我不清楚动态SQL的这种特殊使用是如何不安全的。哪怕是微不足道的修改,都会使int列表足以改变SQL,从而成为一个问题?(如果你的意思是,在以后的某个时候,列表被转换为字符串,那么是的,当然这会是一个问题。)@MichaelTodd Right,确切地说:将
list
更改为
list
,以便在主键是字符串而不是整数的不同表上使用它,依我看,这是一个微不足道的修改。我想我们基本上是一致的:如果您只处理
int
s,并且不在
int
s之前添加任何可能与负值符号结合的内容,那么SQL注入是不可能的。不要为此使用XML。这正是TVP的目的。TVP可以作为参数发送到存储过程,没错,TVP看起来很干净。但由于只有逗号分隔的整数,我提供了额外的选项。在