2016-08-23 11 views
1

私はdataboundチェックボックスリストを使用しているWebアプリケーションを持っています。私はforeachループ内に配置された更新ストアドプロシージャを持っています。 1つのCheckboxListがチェックされていれば、アップデートは正常ですが、1つ以上チェックされていれば、接続はオープンエラーです。接続が閉じられていない、接続の現在の状態がforeachループで開いているエラー

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 
+1

エラーはかなり説明的です。開いている接続を開くことはできません。ループ内で接続を開いていますが、ループ内で閉じているわけではありません。宣言/初期化の直後に開いてください。さらに、SqlCommandとSqlConnectionは、個別のClose呼び出しを使用する代わりにブロックを使用してラップします。 –

答えて

4
SQLは、あなたの foreachループの前に、あなたの conn.Open();コールを移動

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(); 
私は try{}catch{}finally{}を試みたが、それはまだ私に同じエラーを与えています。何が起こっている

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が

は、データソースまたはサーバーを指定せずに接続を開くことができません。 または 接続は既に開いています。

+0

も効率的にパラメータをクリアするでしょうか?私はそれをテストし、今や引数が多すぎると指定されています。これはループのせいだろうか? – walangala

+0

あなたの提案だけでなく、@ Javad_Amiryがパラメータをクリアすることについて何を追加しましたか、もうどちらのエラーも発生しません。ありがとうございます – walangala

+0

これは、ほとんど何が起こっているの簡単な説明です。これを行うことで、コールごとの接続のオープンやクローズなど、さまざまな改善が可能です。データベースへの多数の呼び出しを行い、トラフィックが多い場合は、@ Javad_Amiryが示唆しているようなより多くの予防措置が必要になります。 – Kirk

1

conn.Openはforeachの外にある必要があります。

一度開くと、それは2番目のitem.Selectedに再び開こうとしています。

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 
    } 


    } 

UPDATE: OK。私は@ Krikの答えを見て、私は説明する必要があります:

接続を可能にして、すぐにそれを閉じることができます。ここで、データベースに関連しない操作をいくつか行っているので、ループを介して接続を開いたままにしてはいけません。コマンドのパラメータをクリアして補充するなど。したがって、これは理想的です:

conn.Open(); 
cmd.ExecuteNonQuery(); 
conn.Close(); 
関連する問題