使用字符串生成器和许多参数构建sql查询

时间:2018-03-16 09:00:56

标签: c# sql .net sql-server

我正在使用循环

构建查询
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

如果它为空则它将起作用,否则实际值将没有“”

事情是我不能使用像

这样的东西
@MatchValue

因为我有相同名称的参数列表,这些参数仅与列表中的数字不同,所以名称将相同,并且不会正确映射

2 个答案:

答案 0 :(得分: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等 - 然后您就没有注入漏洞。需要注意的一件事:null 的参数未发送,因此检查null并生成不同的SQL,或者确定在这种情况下将参数值设置为DBNull.Value

答案 1 :(得分:1)

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

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

    public void connect() {
        try {
            JSch jsch = new JSch();
            if(!"${company.sftp.password}".equals(password)){
                session = jsch.getSession(username, host);
                session.setPassword(password);
            }
            else {
                jsch.addIdentity(keyPath);
                session = jsch.getSession(username,host);
            }
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            logger.info("Connection to {}", host);
            sftpChannel = (ChannelSftp) session.openChannel("sftp");
            sftpChannel.connect();
            logger.info("Connected to sftp");
            sftpChannel.cd(path);
            logger.info("Using directory {}", path);
        } catch (JSchException e) {
            logger.error("Cannot connect to sftp", e);
        } catch (SftpException e) {
            logger.error("Problem with sftp connection", e);
        }
}

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

// 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);