2012-12-06 3 views
1

내 코드에서 수동 이탈을 제거하고 싶습니다. 이 대신 SqlParameter 개체를 사용하고 싶습니다.루프에서 SqlParameters를 추가하는 방법?

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(); 
    } 
} 
+0

[무엇을 시도해 봤습니까?] (http://whathaveyoutried.com)? 어디서 붙어 있는지 설명하십시오. – Oded

+0

Replace (" '", "' '")를하고 싶지 않습니다. 이것 대신 newMessage와 oldMessage를 추가하기 위해 SqlParameters를 사용하고 싶습니다. – Vytalyi

+0

예, 당신이 무엇을 원하는지 이해합니다. 나는 네가 ** 시도한 ** 물었습니다. – Oded

답변

1

당신은 지금 거의 같은 방법으로 그것을 할 수 있습니다 - 루프에 insert를 포맷하여, 대신 새로운/오래 된 쌍 당 하나 개의 삽입을 사용하는 모든 쌍에 대해 하나의 문을 사용합니다. 테이블의 열 순서 (프로덕션에서는 커다란 no-no)에 의존하지 않으려면 항상 열 이름을 사용해야하며 항상 NULL을 보내더라도 두 번째 매개 변수를 루프에 작성하지 않아야합니다.

:이 작업을 수행 할 수 있도록

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

또한, 각 매개 변수에 대한 Tuple<long,string,string>의 목록을 가지고 :이 시점에서

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 문자열을
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(); 
    } 
} 

한 번에 그 일의 장점은 상관없이 삽입해야합니다 얼마나 많은 레코드를 데이터베이스에 하나의 왕복을하지 않는다는 것이다. 그 외에도 솔루션은 현재 패턴과 동일한 패턴을 따르므로 성능은 비슷해야합니다.

+0

자세한 답변 해 주셔서 감사합니다! – Vytalyi

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; 

} 
+0

잘 보입니다. 어떻게 생각하십니까? 10k 레코드가 있으면 어떻게 느려 집니까? – Vytalyi

+0

이것은 SQLParameters에 값을 동적으로 추가하는 방법입니다. 값이 매번 변경되므로 AddWithValue()를 사용하여 값을 추가 할 수 없습니다. 내 생각에 시간은 foreach 루프의 실행 시간과 거의 같습니다. – SKJ

1

형 sqlcmd.Parameters.Clear(); before sqlcmd.Parameters.AddWithValue ("@sample", sample);

관련 문제