2

我想从我的代码中删除手动转义。而不是这个我想使用 SqlParameter 对象。

foreach (ThreadPost post in ThreadPosts)
{
     string newMessage = Clean(post.Message);
     string oldMessage = post.Message;

     // escape ' character for prevent errors in SQL script
     // I want to pass newMessage and oldMessage as an SqlParameters to prevent unexpected changes, but how it could be done based on the code bellow???
     newMessage = newMessage.Replace("'", "''");
     oldMessage = oldMessage.Replace("'", "''");

     cmdText += string.Format("INSERT INTO ThreadCleanup VALUES ({0}, {1}, '{2}', '{3}')",
          post.ID.ToString(),
          "NULL",
          oldMessage,
          newMessage);
     }
}
if (!string.IsNullOrEmpty(cmdText))
{
     using (SqlConnection con = new SqlConnection(CONNSTR))
     {
          con.Open();
          SqlTransaction tran = con.BeginTransaction(IsolationLevel.ReadUncommitted);
          try
          {
              using (SqlCommand cmd = new SqlCommand(cmdText, con, tran))
              {
                 cmd.ExecuteNonQuery(); // updated records
              }
              tran.Commit();
          }
          catch (SqlException ex)
          {
              tran.Rollback();
          }
          con.Close();
     }
}
4

3 回答 3

2

您可以以与现在大致相同的方式进行操作 - 通过insert在循环中格式化 an,但不是为每个新/旧对使用一个插入,而是对所有对使用一个语句。您应该明确使用列名以避免依赖表中的列顺序(生产中的一个大禁忌)并避免在循环中创建第二个参数,即使您总是向NULL它发送 a。

var cmdText = new StringBuilder("INSERT INTO ThreadCleanup (id,oldMessage,newMessage) VALUES ");
var args = new List<Tuple<long,string,string>>();
foreach (ThreadPost post in ThreadPosts) {
     int cnt = args.Count();
     if (cnt != 0) {
         cmdText.Append(",");
     }
     cmdText.AppendFormat("(@id{0}, @old{0}, @new{0})", cnt);
     args.Add(new Tuple<long,string,string>(post.ID, post.Message, Clean(post.Message)));
}

此时,您有一个如下所示的 SQL 字符串:

INSERT INTO ThreadCleanup (id,oldMessage,newMessage) VALUES
(@id0, @old0, @new0), (@id1, @old1, @new1), (@id2, @old2, @new2), ...

您还有Tuple<long,string,string>每个参数的列表,因此您可以这样做:

if (args.Count != 0) {
    using (SqlConnection con = new SqlConnection(CONNSTR)) {
        con.Open();
        SqlTransaction tran = con.BeginTransaction(IsolationLevel.ReadUncommitted);
        try {
            using (SqlCommand cmd = new SqlCommand(cmdText, con, tran)) {
               for (var i = 0 ; i != args.Count ; i++) {
                   cmd.Parameters.AddWithValue("@id"+i, args[i].Item1);
                   cmd.Parameters.AddWithValue("@old"+i, args[i].Item2);
                   cmd.Parameters.AddWithValue("@new"+i, args[i].Item3);
               }
               cmd.ExecuteNonQuery(); // updated records
            }
            tran.Commit();
        } catch (SqlException ex) {
            tran.Rollback();
        }
        con.Close();
    }
}

一次性完成的好处是,无论您必须插入多少条记录,您都可以对数据库进行一次往返。除此之外,该解决方案与您当前的解决方案遵循相同的模式,因此性能应该具有可比性。

于 2012-12-06T11:05:45.397 回答
1

在 foreach 循环之外声明您的插入命令。然后将 SQLParameters 添加到命令中。

String cmdInsert= "INSERT INTO ThreadCleanup VALUES(@value1,@value2,@value3,@value4)"
        cmdInsert.Parameters.AddWithValue("@value1", System.Data.SqlDbType.VarChar);
        cmdInsert.Parameters.AddWithValue("@value2", System.Data.SqlDbType.VarChar);
        cmdInsert.Parameters.AddWithValue("@value3", System.Data.SqlDbType.VarChar);
        cmdInsert.Parameters.AddWithValue("@value4", System.Data.SqlDbType.VarChar);

然后在 foreach 循环中分配值。

foreach (ThreadPost post in ThreadPosts)
{
 string newMessage = Clean(post.Message);
 string oldMessage = post.Message;

 // escape ' character for prevent errors in SQL script
 // I want to pass newMessage and oldMessage as an SqlParameters to prevent unexpected changes, but how it could be done based on the code bellow???
 newMessage = newMessage.Replace("'", "''");
 oldMessage = oldMessage.Replace("'", "''");

cmdInsert.Parameters["@value1"].Value = post.ID.ToString();
cmdInsert.Parameters["@value2"].Value = DBNull.Value;
cmdInsert.Parameters["@value3"].Value = oldMessage;
cmdInsert.Parameters["@value4"].Value = newMessage;

}
于 2012-12-06T10:54:05.257 回答
1

输入 sqlcmd.Parameters.Clear(); 之前 sqlcmd.Parameters.AddWithValue("@sample",sample);

于 2014-08-14T17:42:02.093 回答