我想从我的代码中删除手动转义。相反,我想使用 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();
}
}
最佳答案
您可以按照与现在大致相同的方式进行操作 - 通过格式化 insert
在循环中,但不是对每个新/旧对使用一个插入,而是对所有对使用一个语句。您应该显式使用列名,以避免依赖表中的列顺序(生产中的一大禁忌),并避免在循环中创建第二个参数,即使您始终发送 NULL
到它。
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();
}
}
一次性执行此操作的优点是,无论您必须插入多少条记录,您都可以对数据库进行一次往返。除此之外,该解决方案遵循与当前解决方案相同的模式,因此性能应该具有可比性。
关于c# - 如何在循环中添加SqlParameters?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13741879/