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

in a ループをフォーマットすることにより、現在とほぼ同じ方法で実行できますがinsert、新しい/古いペアごとに 1 つの挿入を使用する代わりに、すべてのペアに対して 1 つのステートメントを使用します。列名を明示的に使用して、テーブル内の列の順序に依存することを回避し (本番環境では大問題)、ループ内で 2 番目のパラメーターを作成しないようにする必要があります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();
    }
}

一度に行う利点は、挿入する必要があるレコードの数に関係なく、データベースへの 1 回の往復を行うことです。それ以外は、ソリューションは現在のものと同じパターンに従うため、パフォーマンスは同等である必要があります。

于 2012-12-06T11:05:45.397 に答える
1

foreach ループの外で Insert コマンドを宣言します。次に、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

type sqlcmd.Parameters.Clear(); 前に sqlcmd.Parameters.AddWithValue ("@sample",sample);

于 2014-08-14T17:42:02.093 に答える