C#SQLite使用动态参数插入函数

时间:2014-01-28 23:28:30

标签: c# sqlite parameters

好吧,也许标题有点奇怪,但我会尝试解释它。

我正在使用SQLite数据库文件处理C#应用程序。我有一个DB类,其中所有与db通信的函数都是。

我的代码中有一个Insert函数(注意,这不是由我做的):

public bool Insert(String tableName, Dictionary<String, String> data)
        {
            String columns = "";
            String values = "";
            Boolean returnCode = true;
            foreach (KeyValuePair<String, String> val in data)
            {
                columns += String.Format(" {0},", val.Key.ToString());
                values += String.Format(" '{0}',", val.Value);
            }
            columns = columns.Substring(0, columns.Length - 1);
            values = values.Substring(0, values.Length - 1);
            try
            {
                this.ExecuteNonQuery(String.Format("insert into {0}({1}) values({2});", tableName, columns, values));
            }
            catch (Exception fail)
            {
                MessageBox.Show(fail.Message);
                returnCode = false;
            }
            return returnCode;
        }

一切看起来都不错。但是我希望通过参数化查询来阻止某些SQLInjection。但问题是,查询永远不会有相同的长度。那我该如何处理呢?

我的意思是:我希望这个单个函数用于包含3列的表,以及用于包含8列的表。全部动态。有没有人知道如何做到这一点(以一种很好/正确的方式)?

1 个答案:

答案 0 :(得分:1)

我将插入函数重写为 InsertSecure 方法,
现在您可以使用参数插入所有值。

我在代码中添加了一些注释,以便更好地了解如何调整您的程序 然后,您可以通过这种方式将其称为

public void HowToCall()
{
    // I assume that "columnA" and "columnB" is set by you and it is safe, 
    // unsafe are values "valueA" and "valueB"
    Dictionary<string, string> data = new Dictionary<string, string>()
        { { "columnA", "valueA" }, { "columnB", "valueB" } };
    // then call new method
    InsertSecure("table_name", data);
}

InsertSecure 内容:

public bool InsertSecure(String tableName, Dictionary<String, String> data)
{
    // table name can not contains space
    if (tableName.Contains(' ')) { return false; }
    String columns = "";
    String values = "";
    Boolean returnCode = true;
    foreach (KeyValuePair<String, String> val in data)
    {
        columns += String.Format(" '{0}',", val.Key.ToString());
        // all values as parameters
        values += String.Format(" @{0},", val.Key.ToString());
    }
    columns = columns.Substring(0, columns.Length - 1);
    values = values.Substring(0, values.Length - 1);
    try
    {
        // setup your connection here
        // (connection is probably set in your original ExecuteNonQuery)
        SQLiteConnection cnn = new SQLiteConnection(); 
        cnn.Open();
        SQLiteCommand cmd = cnn.CreateCommand();
        cmd.CommandType = System.Data.CommandType.Text;
        // prepare insert command based on data
        cmd.CommandText = String.Format("insert into {0} ({1}) values ({2})",
            tableName, columns, values);

        // now your command looks like:
        // insert into table_name (columnA, columnB) values (@columnA, @columnB)
        // next we can set values for any numbers of columns
        // over parameters to prevent SQL injection
        foreach (KeyValuePair<String, String> val in data)
        {
            // safe way to add parameter
            cmd.Parameters.Add(
                new SQLiteParameter("@" + val.Key.ToString(), val.Value));
            // you just added for @columnA parameter value valueA
            // and so for @columnB in this foreach loop
        }
        // execute new insert with parameters
        cmd.ExecuteNonQuery();
        // close connection and set return code to true
        cnn.Close();
        returnCode = true;
    }
    catch (Exception fail)
    {
        MessageBox.Show(fail.Message);
        returnCode = false;
    }
    return returnCode;
}

我可以通过此程序安全地插入数据。

注意:我没有测试它的项目,如果它被正确写入,
但是没有语法错误,逻辑看起来还不错。请尝试并享受。