使用相同的参数化查询添加多个SQL值?

时间:2016-10-28 18:13:49

标签: c# sql .net sql-server database

我对SQL很新,并试图找出添加一些预定义数据的最佳方法。我想通过在这里搜索我应该使用参数化命令来避免sql注入攻击,这在这种情况下不是一个大问题,但我想避免这种可能性,并学会正确做...无论如何这里是我现在的代码:

        using (SqlTransaction trans = connection.BeginTransaction())
        {
            foreach (IEnumerable<string> row in table.RowData)
            {
                using (SqlCommand sql = new SqlCommand("INSERT INTO " + table.Title
                    + " (" + string.Join(", ", table.Headers)
                    + ") VALUES (" + string.Join(", ", table.Headers.Select(x => "@" + x)) + ");", connection, trans))
                {

                    for (int i = 0; i < table.Headers.Count(); i++)
                    {
                        if (string.IsNullOrEmpty(row.ElementAt(i)))
                        { sql.Parameters.AddWithValue("@" + table.Headers.ElementAt(i), DBNull.Value); }
                        else
                        { sql.Parameters.AddWithValue("@" + table.Headers.ElementAt(i), row.ElementAt(i)); }
                    }
                    sql.ExecuteNonQuery();
                }
            }
            trans.Commit();
        }

这似乎有效,所有数据都在那里,但对我来说感觉“效率低下”。我将它包装在一个事务中,所以只有一个提交,但它每次都创建参数,只是为每一行设置不同的值。

有没有办法让它使用相同的参数,但每行只设置不同的值?或者这是最好的方法,我不应该担心吗?

提前感谢您提供任何帮助。

3 个答案:

答案 0 :(得分:2)

我们可以通过在预处理步骤中将标题解析为参数来执行您想要的操作。我还删除了显式事务,因为默认情况下每个插入都已经获得了一个隐式事务(为什么要支付两个事务的性能损失?)。

using (var command = new SqlCommand()) {
    command.CommandText =
        "INSERT INTO " + table.Title + " ("
      + string.Join(", ", table.Headers)
      + ") VALUES ("
      + string.Join(", ", table.Headers.Select(x => "@" + x))
      + ");";
    command.Connection = connection;

    foreach (var header in table.Headers) {
        /*
             Add all parameters as strings. One could choose to infer the
             data types by inspecting the first N rows or by using some sort
             of specification to map the types from A to B.
         */
        command.Parameters.Add("@" + header, typeof(string));
    }

    foreach (var row in table.RowData) {
        for (var i = 0; i < table.Headers.Count(); i++) {
            if (!string.IsNullOrEmpty(row.ElementAt(i))) {
                command.Parameters["@" + table.Headers.ElementAt(i)].Value = row.ElementAt(i);
            }
            else {
                command.Parameters["@" + table.Headers.ElementAt(i)].Value = DBNull.Value;
            }
        }

        command.ExecuteNonQuery();
    }
}

答案 1 :(得分:0)

是的,通过重用SqlParameter对象可以更有效。这是一些伪代码:

        const string sql = "INSERT INTO table1 (column1) VALUES (@p0)";
        using (var sqlCommand = new SqlCommand(sql, connection, transaction))
        {
            var param1 = sqlCommand.Parameters.Add("@p0", SqlDbType.Int);
            foreach (var row in table)
            {
                param1.Value = row["value"];
                sqlCommand.ExecuteNonQuery();
            }
        }

答案 2 :(得分:0)

这是我的插件示例,适用于我

  private void insertWordCount(string songId, string wordId, int wordCount)
    {
        string query = "insert into songs_words_conn values(@wordId,@songId,@wordCount)";
        SqlCommand cmd = new SqlCommand(query, conn);

        cmd.Parameters.AddWithValue("@wordId", wordId);
        cmd.Parameters.AddWithValue("@songId", songId);
        cmd.Parameters.AddWithValue("@wordCount", wordCount);

        cmd.ExecuteNonQuery();
    }