如何使用npgsql中的参数在单个命令中更新多行中的列值?

时间:2015-04-07 18:18:11

标签: c# postgresql npgsql

因此,我尝试做的是在用户返回并编辑/更改以前的答案时,使用新值更新答案表。因此,调查问卷有20个问题,用户填写,然后在Questionnaire_ResponseTable中保存,如果他们返回并更改他们的答案,我想更新表格。很简单。

棘手的部分是我想防止SQL注入,所以当我构建我的" stmnt"我将用户答案作为参数插入(以防他们尝试做一些阴暗的事情)。问题是因为我试图更新说我在单个数据库命令中的所有20行":回答"多次说明。我发现的是npgsql处理所有":answer"相同。所以当我去修改数据库中的20rows时,每行对应一个用户回答的问题。而不是获得20行与20个唯一答案的每一行最终得到相同的答案更新。

我尝试使用string.format做类似":回答{0}",我要区分":回答"'但是确实有效抛出一个例外。通过不使用参数来插入用户提供的答案,我已经完成了所有工作,所以我知道我的posgresql命令可以解决问题,只是以安全的方式来防止注入。

public void UpdateAnswers(List<string> paramAnswers) {
        List<string> answers = paramAnswers;
        string stmnt = "UPDATE demographic_responses AS dr SET answer = c.answer FROM (values ";

        string updateVals = "";
        for (int i = 1; i <= answers.Count; i++) {
            updateVals = updateVals + string.Format("("+"'"+((App)Application.Current).participantDM.id+"',"+ "'"+i+"'," + ":answer{0}),",i);
        }
        updateVals = updateVals.Substring(0, updateVals.Length-1);

        stmnt = stmnt + updateVals + ") AS c(user_id, question_id, answer) WHERE c.question_id = dr.question_id AND c.user_id = dr.user_id";

        using (NpgsqlConnection conn = PgConnection.GetConnection()) {
            using (NpgsqlCommand cmd = new NpgsqlCommand(stmnt, conn)) {
                for (int i = 0; i < answers.Count; i++) {
                    cmd.Parameters.Add(PgHelpers.ToNpgsqlParameter(DemographicResponseTable.Column.answer));
                    cmd.Parameters[i].Value = answers[i];
                }
                    cmd.ExecuteNonQuery();
            }
        }
    }

1 个答案:

答案 0 :(得分:0)

设置参数而不实际将其发送到数据库(例如使用ExecuteNonQuery),就像你在代码中所做的一样,绝对没有做任何事情;这不是Npgsql特有的行为,它是一般的数据库/ ADO.NET行为。

为了帮助您理解,从概念上讲,参数与在SQL查询中直接插入值不同(当然,除了注入保护和性能优势之外)。

如果您尝试通过不向数据库发送X查询来优化性能,请考虑将架构更改为包含多个答案的单行,其中对问题的响应表示为列而不是行。

Npgsql当前不支持的另一个选项是在一个命令中发送多个UPDATE SQL语句,而不是为每个命令执行ExecuteNonQuery(后者发送SQL并等待响应)。不幸的是,这当前与参数不兼容(但将在Npgsql的下一个主要版本中得到支持)。