2013-02-21 65 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