2014-05-02 123 views
0

我創建了一個銷售表,其插入功能無法正常工作。它顯示如下錯誤消息「ExecuteNonQuery需要一個開放的可用連接,連接的當前狀態爲關閉」如果我刪除了第14行的Sql關閉語句,則顯示此錯誤消息msg 「已經有一個打開的DataReader關聯這個命令必須先關閉。「我的代碼如下工作。我從我的產品表中檢查了可用庫存。如果數量訂單大於產品表中的數量,則顯示錯誤消息。否則,請繼續將訂單信息插入到銷售表中。任何幫助表示讚賞。插入Sql功能不起作用

private void btnOrder_Click(object sender, EventArgs e) 
    { 
     int iQuantityDB; 
     int iCustomerID = Convert.ToInt32(txtCustomerID.Text); 
     int iProductID = Convert.ToInt32(txtProductID.Text); 
     decimal dPrice = Convert.ToDecimal(txtPrice.Text); 
     int iQuantity = Convert.ToInt32(txtQuantity.Text); 
     decimal dSubtotal = Convert.ToDecimal(txtSubTotal.Text); 
     decimal dGST = Convert.ToDecimal(txtGST.Text); 
     decimal dTotal = Convert.ToDecimal(txtTotal.Text); 
 string strConnectionString = @"Data Source = KK\SQLEXPRESS; Integrated Security = SSPI; Initial Catalog = JeanDB; MultipleActiveResultSets=True;"; 
     using (var sqlconn = new SqlConnection(strConnectionString)) 
     { 
      sqlconn.Open(); 
      string querySelectQuantity = @"Select Quantity from dbo.JeanProduct WHERE ProductID = @iProductID"; 
      using (var cmdOrder = new SqlCommand(querySelectQuantity, sqlconn)) 
      { 

       using (var sdRead = cmdOrder.ExecuteReader()) 
       { 
        sdRead.Read(); 
        iQuantityDB = Convert.ToInt32(sdRead["Quantity"]); 

       } 
      } 
      if (iQuantityDB > iQuantity) 
      { 
       string InsertQuery = @"INSERT INTO Sale(CustomerID, ProductID, Price, Quantity, Subtotal, GST, Total)VALUES(@iCustomerID, @iProductID, @dPrice, @iQuantity, @dSubtotal, @dGST, @Total)"; 
       using (var InsertCMD = new SqlCommand(InsertQuery, sqlconn)) 
       { 
        InsertCMD.Connection = sqlconn; 

        InsertCMD.Parameters.AddWithValue("@iCustomerID", iCustomerID); 
        InsertCMD.Parameters.AddWithValue("@iProdcutID", iProductID); 
        InsertCMD.Parameters.AddWithValue("@dPrice", dPrice); 
        InsertCMD.Parameters.AddWithValue("@iQuantity", iQuantity); 
        InsertCMD.Parameters.AddWithValue("@dSubtotal", dSubtotal); 
        InsertCMD.Parameters.AddWithValue("@dGST", dGST); 
        InsertCMD.Parameters.AddWithValue("@dTotal", dTotal); 
        InsertCMD.ExecuteNonQuery(); 


        LoadDataonTable(); 
       } 

      } 

      else 
      { 
       MessageBox.Show("no more stock"); 

      } 
      sqlconn.Close(); 

     } 

    } 
+1

爲什麼不使用'ExecuteReader',爲什麼不使用'ExecuteScalar',因爲它看起來像你不想*讓* sdRead'讀者打開? –

回答

1

您應該將連接字符串更改爲

string strConnectionString = @"Data Source = KK\SQLEXPRESS; 
           Integrated Security = SSPI; 
           Initial Catalog = JeanDB; 
           MultipleActiveResultSets=True"; 

不要關閉Reader.Read和爲ExecuteNonQuery之間的連接。 您至少需要Sql Server 2005才能正常工作。

除非使用MultipleActiveResultSets鍵設置連接字符串,否則SqlDataReader使用的連接不能用於其他操作。當然你可以打開兩個連接對象(具有相同的連接字符串),並使用一個用於SqlDataReader,另一個用來執行你的命令。

沒有真正的鏈接到您的問題,但我建議也使用參數化查詢也爲您的代碼的SELECT部分​​。

此外,您應該圍繞一次性物品使用Using Statement以確保在出現異常情況時也能正確關閉和處理。最後,INSERT INTO中使用的語法不正確。我認爲這段代碼可以解釋上面解釋的一些觀點。

string strConnectionString = @"......;MultipleActiveResultSets=True;"; 
using(SqlConnection sqlconn = new SqlConnection(strConnectionString)) 
{ 
    sqlconn.Open(); 
    string querySelectQuantity = @"Select Quantity from dbo.JeanProduct 
            WHERE ProductID = @id"; 
    using(SqlCommand cmdOrder = new SqlCommand(querySelectQuantity, sqlconn)) 
    { 
     cmdOrder.AddWithValue("@id", Convert.ToInt32(txtProductID.Text)); 
     using(SqlDataReader sdRead = cmdOrder.ExecuteReader()) 
     { 
      if(sdRead.Read()) 
      { 
       ..... 
       string InsertQuery = @"INSERT INTO Sale(SaleID, CustomerID, ProductID, 
        Price, Quantity, Subtotal, GST, Total)VALUES(@iCustomerID, 
        @iProductID, @dPrice, @iQuantity, 
        @dSubtotal, @dGST, @Total)"; 
        using(SqlCommand InsertCMD = new SqlCommand(InsertQuery, sqlconn)) 
        { 
         InsertCMD.Parameters.AddWithValue("@iCustomerID", iCustomerID); 
         .... 
         InsertCMD.ExecuteNonQuery(); 
         LoadDataonTable(); 
        } 
      } 
      else 
      { 
        MessageBox.Show("no more stock"); 
      } 
     } 
    } 
} 
1

您關閉SqlConnection讀者執行/讀週期後(和其他錯誤,你已經把讀者開放,而試圖執行另一個命令)。

請關閉閱讀器並將連接保持爲打開插入位置,或打開插入的新連接。

更妙的是,使用using處理處置的資源爲你,並儘快公佈範圍的數據庫資源,你與他們所做的,如:

using (var sqlconn = new SqlConnection(strConnectionString)) 
{ 
    sqlconn.Open(); 

    string querySelectQuantity = "Select Quantity ..."; 
    using var (cmdOrder = new SqlCommand(querySelectQuantity, sqlconn)) 
    { 
     int iQuantityDB; 
     using (var sdRead = cmdOrder.ExecuteReader()) 
     { 
      sdRead.Read(); 
      iQuantityDB = Convert.ToInt32(sdRead["Quantity"]); 
     } // Dispose reader 
     // sqlconn.Close(); <-- Don't close 
    } // cmdOrder disposed here 

    if (iQuantityDB > iQuantity) 
    { 
     string InsertQuery = "INSERT INTO ..."; 
     using var (InsertCMD = new SqlCommand(InsertQuery, sqlconn)) 
     { 
      // ... 
     } // InsertCmd disposed here 
    } 
} // Sql Connection disposed here 

這將克服許多錯誤,比如你有條件地關閉if分支中的命令+連接的地方。

+0

謝謝大家的幫忙。我遵循你的建議,並用「使用」改變了編碼。但我仍然有錯誤語句「不正確的語法附近'='。」在InsertCMD.ExecuteNonQuery()的行;任何想法。我進行了調試並逐行閱讀,找不到錯誤的地方。 – kkcoder

+0

您還需要在插入時遵循Steve的建議 - 語法爲INSERT INTO Table(Col1,Col2,....)VALUES(@ Col1,@ Col2 ...)'(不是'Col1 = @ Col1')。此外,您正在列出「SaleId」列但沒有值 - 值的數量必須與指定的列匹配。如果它是一個標識列,則將其從列表中刪除。如果您仍然陷入困境,請在您的問題下面粘貼更新的Sql,或者提出一個全新的問題。如果你只需要從一行中讀取一列值,達米恩關於ExecuteScalar vs Reader的觀點也是一個很好的觀點。 – StuartLC

+0

謝謝。我會創建一個新的問題。 – kkcoder