2016-08-23 72 views
1

我有一個使用數據綁定複選框列表的Web應用程序。我有一個更新存儲過程,我放在一個foreach循環中。如果選中了一個CheckboxList,則更新沒問題,但是如果我檢查了多個CheckboxList,則會拋出該連接爲打開錯誤。我嘗試了try{}catch{}finally{}但它仍然給了我同樣的錯誤連接未關閉,連接的當前狀態爲foreach循環中的打開錯誤

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

該錯誤的描述性很好。您無法打開打開的連接。您正在循環中打開您的連接,但不會在循環中關閉它。在聲明/初始化之後立即將open打開,你應該很好。此外,用塊代替你的SqlCommand和SqlConnection,而不是使用離散的Close調用。 –

回答

4
foreach循環前

移動你conn.Open();電話。

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()已經打開的連接,它會引發錯誤。這就是爲什麼第一次通話有效,而下一次通話失敗。

請看MSDN documentationOpen()方法。它有一些會導致例外的例子。

在這種情況下

InvalidOperationException異常

無法打開而不指定數據源或服務器的連接。 或 連接已經打開。

+0

會清除參數也有效嗎?我測試了,現在得到了太多的參數指定的錯誤。這可能是因爲循環? – walangala

+0

我添加了你的建議以及@Javad_Amiry有關清除參數的信息,而且我再也沒有看到任何錯誤。謝謝 – walangala

+0

這主要是對正在發生的事情的簡單描述。您可以通過多種方式進行改進,例如爲每個呼叫打開和關閉連接等。如果您對數據庫進行大量呼叫並且流量很大,那麼您需要採取更多預防措施,例如@Javad_Amiry建議的內容。 – Kirk

1

conn.Open應該在foreach之外。

一旦打開。它正試圖再次打開第二個項目。已選中。

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:確定。我看到了@ Krik的回答,我需要描述:

使用ADO.NET的基本規則之一是:打開一個連接儘可能晚,並儘可能地關閉它。所以,你不應該通過一個循環保持打開連接,因爲你在這裏做一些非數據庫相關的操作。如清除命令的參數並重新填充。所以,這將是理想的:

conn.Open(); 
cmd.ExecuteNonQuery(); 
conn.Close(); 
相關問題