连接未关闭,连接的当前状态是foreach循环中的打开错误

时间:2016-08-23 15:56:24

标签: c# asp.net sql-server

我有一个使用数据绑定列表的网络应用程序。我有一个更新存储过程,我放在foreach循环中。如果选中了一个CheckboxList,则更新很好,但如果我检查了多个,则会抛出连接打开错误。我尝试了try{}catch{}finally{},但它仍然给我同样的错误

CultureInfo provider = CultureInfo.InvariantCulture;
System.Globalization.DateTimeStyles style = DateTimeStyles.None;
DateTime dt;
DateTime.TryParseExact(datepicker.Text, "mmddy", provider, style, out dt);
int i = Int32.Parse(amount.Text);

SqlConnection conn = new SqlConnection(GetConnectionString());
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;


 foreach (ListItem item in CheckBoxList1.Items)
 {
     if(item.Selected)
     {

          cmd.CommandType = CommandType.StoredProcedure;
          cmd.CommandText = "[dbo].[AccountCode_Update]";
          cmd.Parameters.AddWithValue("@Batch_Num", SqlDbType.Int).Value = i;
          cmd.Parameters.AddWithValue("@Batch_Date", SqlDbType.DateTime).Value = dt;
          cmd.Parameters.AddWithValue("@Account_Code", SqlDbType.VarChar).Value = BatchCodeList.SelectedValue;
          conn.Open();
          cmd.ExecuteNonQuery();
     }


  }
  conn.Close();

SQL

CREATE TABLE AccountTable
(
  RowID int IDENTITY(1, 1),
  AccountID varchar(2),
  AccountName varchar(50),
  SeqNum int,
  SeqDate datetime
)

CREATE PROCEDURE [AccountCode_Update]
(
  @Batch_Num int,
  @Batch_Date datetime,
  @Account_Code varchar(2)
)

 AS 
 SET NOCOUNT ON
 BEGIN
  UPDATE AccountTable
   SET SeqNum = @Batch_Num, SeqDate = @Batch_Date
   WHERE AccountID = @Account_Account_Code
 END

3 个答案:

答案 0 :(得分:5)

conn.Open();循环之前移动foreach来电。

SqlConnection conn = new SqlConnection(GetConnectionString());
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;

conn.Open();

foreach (ListItem item in CheckBoxList1.Items)
{
    if(item.Selected)
    {

        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = "[dbo].[AccountCode_Update]";
        cmd.Parameters.AddWithValue("@Batch_Num", SqlDbType.Int).Value = i;
        cmd.Parameters.AddWithValue("@Batch_Date", SqlDbType.DateTime).Value = dt;
        cmd.Parameters.AddWithValue("@Account_Code", SqlDbType.VarChar).Value = BatchCodeList.SelectedValue;

        cmd.ExecuteNonQuery();
    }
}

conn.Close();

发生的事情是您正在调用已经打开的连接的conn.Open()并且它会引发错误。这就是第一次通话有效而下一次通话失败的原因。

查看Open()方法的MSDN documentation。它有一些导致异常的例子。

在这种情况下

  

<强>出现InvalidOperationException

     

如果未指定数据源或服务器,则无法打开连接。   要么   此连接已打开。

答案 1 :(得分:2)

关闭连接!此外,您需要在每个循环中清除命令参数。

 foreach (ListItem item in CheckBoxList1.Items)
 {
     if(item.Selected)
     {

          cmd.CommandType = CommandType.StoredProcedure;
          cmd.CommandText = "[dbo].[AccountCode_Update]";
          cmd.Parameters.AddWithValue("@Batch_Num", SqlDbType.Int).Value = i;
          cmd.Parameters.AddWithValue("@Batch_Date", SqlDbType.DateTime).Value = dt;
          cmd.Parameters.AddWithValue("@Account_Code", SqlDbType.VarChar).Value = BatchCodeList.SelectedValue;
          conn.Open();
          cmd.ExecuteNonQuery();
          conn.Close();
          cmd.Parameters.Clear(); // you need to clear previous parameters
     }


  }

更新:确定。我看到@Krik的回答,我需要描述一下:

使用ADO.NET的基本规则之一是:尽可能地打开连接,并尽快关闭它。所以,你不应该保持打开状态通过循环连接,因为你在这里做了一些与数据库无关的操作。如清除命令的参数并重新填充它。所以,这将是理想的:

conn.Open();
cmd.ExecuteNonQuery();
conn.Close();

答案 2 :(得分:1)

conn.Open应该在foreach之外。

一旦打开。它试图再次打开第二项。选择。