2013-02-21 62 views
2

我有以下代碼。SqlDataReader和SqlCommand

using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) 
{ 
    connection.Open(); 
    SqlCommand select = new SqlCommand("SELECT RTRIM(LTRIM(PART_NO)) AS PART_NO, record FROM [RMAData].[dbo].[IMPORTING_ORDER_EDI] WHERE sessionID = '" + Session.SessionID + "'", connection); 

    SqlDataReader reader = select.ExecuteReader(); 

    if (reader.HasRows) 
    { 
     while (reader.Read()) 
     { 
     if (!currentPart.IsActive) 
     { 
      // this part is not active, set the active flag in sql to 0 
      SqlCommand update = new SqlCommand("UPDATE [RMAData].[dbo].[IMPORTING_ORDER_EDI] SET valid = 0, active = 0 WHERE record = " + reader["record"].ToString() + ";", connection); 

      update.ExecuteNonQuery(); 
     } 
     else 
     { 
      ///blah 
     } 
     } 

     reader.Close(); 
    } 
} 

但這會導致以下異常...

System.InvalidOperationException:有已與此命令必須先關閉相關聯的打開的DataReader 。

我需要讀取返回的每一行,對數據做一些驗證並在必要時進行更新,然後繼續到下一條記錄。如果我在使用reader.Read()循環時不能使用SqlCommand,我該如何實現這一目標?

+0

格蘭特托馬斯的回答是正確的,但它會更有效地記錄您希望設置爲不活動的每個記錄的PK,然後執行單個UPDATE ... WHERE IN(...)讀者。 – Phil 2013-02-21 15:36:55

+0

有趣......就像建立一個PK的數組,你的意思是然後循環通過? – Stuart 2013-02-21 15:41:07

+0

爲什麼你需要選擇並循環每個更新?爲什麼不直接使用select語句的where子句進行更新? – adrianm 2013-02-21 18:19:37

回答

3

另一種是不加MultipleActiveResultSets使用多個連接=真 - 這樣做有一個小的性能損失 - 如此類似 - 例如:

using (SqlConnection connection = new ...)) 
{ 
    connection.Open(); 
    SqlCommand select = new SqlCommand(...); 

    SqlDataReader reader = select.ExecuteReader(); 

    var toInactivate = new List<string>(); 

    if (reader.HasRows) 
    { 
     while (reader.Read()) 
     { 
     if (!currentPart.IsActive) 
     { 
      toInactivate.Add(reader["record"].ToString()); 
     } 
     else 
     { 
      ///blah 
     } 
     } 

     reader.Close(); 
    } 

    SqlCommand update = new SqlCommand("UPDATE ... SET valid = 0, active = 0 " + 
     "WHERE record IN(" + string.Join(",", toInactivate) + ");", connection); 

    update.ExecuteNonQuery(); 
} 

whic h具有在單個SQL語句中更新所有必需記錄的優點。

當然,整個事情會更加整潔,使用EF和Linq。

+0

作爲一個學習者,我很確定在閱讀它之前我已經完成了這件事,Grant Thomas的答案確實有效,但我也注意到了你的評論並更新了我的代碼。尋求幫助! – Stuart 2013-02-22 11:07:59

5

可能是這麼簡單amending your connection string

添加MultipleActiveResultSets = True以連接字符串

+0

Spot-On !!非常感謝你!!我喜歡這個地方! – Stuart 2013-02-21 15:40:08

+0

@Stuart非常歡迎。我也是。 (: – 2013-02-21 15:43:13

3

您需要可以創建你連接的多個實例。
由於只需要一個命令可以對在一個連接中excuted一般


做由@grantThomas建議
或者你可以按如下

using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) 
{ 
    connection.Open(); 
    SqlCommand select = new SqlCommand("SELECT RTRIM(LTRIM(PART_NO)) AS PART_NO, record FROM [RMAData].[dbo].[IMPORTING_ORDER_EDI] WHERE sessionID = '" + Session.SessionID + "'", connection); 

    SqlDataReader reader = select.ExecuteReader(); 

    if (reader.HasRows) 
    { 
     while (reader.Read()) 
     { 
     if (!currentPart.IsActive) 
     { 
      // this part is not active, set the active flag in sql to 0 
      using (SqlConnection connection1 = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) 
      { 
       SqlCommand update = new SqlCommand("UPDATE [RMAData].[dbo].[IMPORTING_ORDER_EDI] SET valid = 0, active = 0 WHERE record = " + reader["record"].ToString() + ";", connection1); 


      update.ExecuteNonQuery(); 
      } 
     } 
     else 
     { 
      ///blah 
     } 
     } 

     reader.Close(); 
    } 
} 
+0

)SqlDataReader循環的這種情況,然後需要訪問每行的其他數據是另一種常見的方式。獲取新連接字符串的另一種方法是將ConnectionString屬性從原始連接複製到「忙碌」與datareader,例如,SqlConnection newConn =新SqlConnection(originalConnection.ConnectionString); – Developer63 2015-11-13 18:26:06

+0

問題是,如果有人更新會話臨時表,該臨時表會被第二個連接看到嗎?我不會這麼認爲,但不會100%肯定 – user441521 2017-01-05 15:45:31