【问题标题】:An issue of SqlCommand with parameters for IN [duplicate]带有 IN 参数的 SqlCommand 问题 [重复]
【发布时间】:2013-05-26 09:19:09
【问题描述】:

显然,以下代码没有按预期打印任何内容。我确信这与我试图将项目列表放入@namelist 的事实有关。显然,它不仅仅是文本替换。

我该如何解决这个问题?谢谢

using (var connection = new SqlConnection(_connectionString))
{
    connection.Open();

    using (var cmd = connection.CreateCommand())
    {
        cmd.CommandText = @"select column_name, table_name from information_schema.columns where table_name in (@namelist)";
        cmd.Parameters.AddWithValue("@namelist",  "'tableOne', 'tableTwo'");

        var reader = cmd.ExecuteReader();

        while (reader.Read())
        {
            var a = reader[0];
            Console.WriteLine(a);
        }
    }
}

【问题讨论】:

  • 嗯,你没有对@namelist做任何事情?
  • 您是否尝试过 @namelist 而不是 addWithValue 中的“TradeName”
  • 我的个人解决方案is this one 答案包括将IEnumerable<string> 转换为IEnumerable<SqlDataRecord> 的扩展方法
  • 从某人那里听说,如果允许的话,可能会出现安全问题。是 sql server 不允许这样做,而不是在 dotnet 层上。有人在这方面有 cmets 吗?

标签: c# sql sql-server


【解决方案1】:

如前所述,“in”列表等在 ado.net 中是出了名的尴尬;正因为如此,一些工具提供了方便的方法来提供帮助。 例如,Dapper 提供了“in”语法的变体,它会自动扩展为正确的参数化形式(仍然保持注入安全等) - 在类型绑定和“动态”使用中。例如:

string[] namelist = ...
foreach(var row in conn.Query(@"
    select column_name, table_name
    from information_schema.columns
    where table_name in @namelist",
        new { namelist } ))
{
    string col = row.column_name,
         table = row.table_name;
    // .. 
}

这也避免了使用 db-command/parameter/reader 的麻烦。注意它用来识别这种模式的“in”没有括号。

【讨论】:

  • Frick 伙计,精巧的不能做什么!
【解决方案2】:

不幸的是,SQL 参数并没有解析,换句话说,后端不只是构建一个安全字符串,用它的值替换每个参数。相反,您必须动态构建参数列表:

cmd.CommandText = @"select column_name, table_name from information_schema.columns where table_name in (@p1, @p2, @p3)"; // This can be built dynamically

然后添加每个参数:

cmd.Parameters.AddWithValue("@p1", "tableOne");
cmd.Parameters.AddWithValue("@p2", "tableTwo");
cmd.Parameters.AddWithValue("@p3", "tableThree");

如果数字在运行时之前未知,您当然可以在循环中添加这些参数:

for(var i = 0; i < myParams.length; i++)
{
   cmd.Parameters.AddWithValue("@p" + i.ToString(), myParams[i]);
}

如果您的表列表存储在enum 中,或者您可以转义它们或使用正则表达式验证它们,那么您自己构建原始 SQL 并且根本不使用参数也是相当安全的。

这当然是我使用PostgreSQL 的一大原因;对数组的原生支持。

【讨论】:

  • Oracle 有关联数组。 SQL Server 具有表值参数。
  • 我检查了一次表值参数,这对我来说太混乱了。 ADO.NET 不仅将数据编组为数组,而且在存储过程中,您必须在此临时表中加入或一些废话。 Postgres 只允许您将 string[] 作为参数传递并执行 WHERE x IN (:myArray) - 您期望它的工作方式。
【解决方案3】:

您现在没有使用您的列表。如果你不需要它来做其他事情,你可以简单地这样做:

 using (var connection = new SqlConnection(_connectionString))
    {
        connection.Open();
        using (var cmd = connection.CreateCommand())
        {
            cmd.CommandText = @"select column_name, table_name from information_schema.columns where table_name in ('tradeName',  'tableOne', 'tableTwo')"

            var reader = cmd.ExecuteReader();

            while (reader.Read())
            {
              var a = reader[0];
              Console.WriteLine(a);
            }
        }

这将检查它是否在这 3 个值中。

【讨论】:

  • -1 没有评论是怎么回事?
猜你喜欢
  • 2011-10-12
  • 1970-01-01
  • 1970-01-01
  • 2014-02-02
  • 2017-04-02
  • 1970-01-01
  • 2019-07-30
  • 2011-03-07
相关资源
最近更新 更多