【问题标题】:Build sql query with string builder and a lot of parameters使用字符串生成器和大量参数构建 sql 查询
【发布时间】:2018-03-16 09:00:56
【问题描述】:

我正在使用循环构建我的查询

for (var i = 0; i <  query.BlackWhiteListFieldMatchProxy.Count; i++)
        {
            sb.Append($@"(
                                MatchType = {(int)query.BlackWhiteListFieldMatchProxy[i].MatchType}
                        AND     EntityType = {(int)query.BlackWhiteListFieldMatchProxy[i].EntityType}
                        AND     MatchFieldType = {(int)query.BlackWhiteListFieldMatchProxy[i].MatchFieldType}
                        AND     (
                                    (
                                        MatchValue = '{query.BlackWhiteListFieldMatchProxy[i].MatchValue1}'
                                        OR MatchValue = {query.BlackWhiteListFieldMatchProxy[i].MatchValue2Or ?? "Null"}
                                    )
                                AND
                                    (
                                        {query.BlackWhiteListFieldMatchProxy[i].MatchValue2And ?? "Null"} is Null
                                        OR MatchValue2 is Null
                                        OR MatchValue2 = {query.BlackWhiteListFieldMatchProxy[i].MatchValue2And ?? "Null"}
                                    )
                                 )
                          )");

            if (i != query.BlackWhiteListFieldMatchProxy.Count - 1)
                sb.Append($@"
                            OR");
        }

但我有这个问题

{query.BlackWhiteListFieldMatchProxy[i].MatchValue2And ?? "Null"} is Null

如果为 Null 则有效,否则真正的值将没有“”

问题是我不能使用类似的东西

@MatchValue

因为我有同名的参数列表,只是列表中的编号不同,因此名称将相同,并且无法正确映射

【问题讨论】:

  • 发布函数的完整代码。
  • 您正在将文字注入 SQL;这是一个非常非常非常糟糕的主意......你说“问题是我不能使用像@MatchValue 这样的东西,因为我有同名的参数列表,只是列表中的数字不同,名称将是相同,它不会正确映射它`-我不明白这是一个问题:只需创建您需要填写查询的任何其他参数。您能否解释更多使用常规参数阻止您的原因在这里?因为我不明白...
  • 我有对象列表 BlackWhiteListFieldMatchProxy。我不知道有多少。每个对象都有 MatchType、EntityType 等。但是每个对象的每个循环中,其字段的值都不同。我将如何使用 @ 映射参数并取决于当前的循环步骤。名称相同,值不同。所有这些都必须组合在一个查询中

标签: c# sql .net sql-server


【解决方案1】:
for (var i = 0; i <  query.BlackWhiteListFieldMatchProxy.Count; i++)
{
    var match = query.BlackWhiteListFieldMatchProxy[i];
    cmd.Parameters.AddWithValue($"@matchType{i}", (int)match.MatchType);
    cmd.Parameters.AddWithValue($"@entityType{i}", (int)match.EntityType);
    cmd.Parameters.AddWithValue($"@fieldType{i}", (int)match.MatchFieldType);

    sb.Append($@"(
                            MatchType = @matchType{i}
                    AND     EntityType = @entityType{i}
                    AND     MatchFieldType = @fieldType{i}
    ... etc

为每个必需的元素添加额外的参数 - 所以会有@matchType0@matchType1 等 - 那么你就没有注入漏洞。需要注意的一点:valuenull 的参数不会发送,因此请检查null 并生成不同的 SQL,或者确保设置参数在这种情况下,值为DBNull.Value

【讨论】:

    【解决方案2】:

    首先,这是构建 SQL 的糟糕方式。这个 SQL 有很多问题。首先也是最重要的是它对 SQL 注入攻击是开放的。但是,它还有其他与性能相关的问题,即只要提供不同的值,SQL 查询就会发生变化。

    我建议你使用参数化 SQL。这是最基本的例子。 请注意,代码可能会根据您要使用的库而有所更改。

    // 1. declare command object with parameter @City
    SqlCommand cmd = new SqlCommand(
        "select * from Customers where city = @City", conn);
    
    // 2. define parameters used in command object
    SqlParameter param  = new SqlParameter();
    param.ParameterName = "@City";
    param.Value         = inputCity;
    

    如果我们回到你的案子。最终代码是这样的:

    "... SQL ...
    MatchType = @matchType AND
     ... SQL ..."
    

    代码需要像

    cmd.Parameters.AddWithValue("@matchType", (int)match.MatchType);
    

    对于空值,您可以考虑使用

    DbNull.Value
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-06
      • 2018-07-03
      • 1970-01-01
      • 2013-09-11
      • 1970-01-01
      • 2015-07-14
      • 2010-12-10
      相关资源
      最近更新 更多