插入Sql函数不起作用

时间:2014-05-02 14:32:14

标签: c# sql insert

我创建了一个销售表,其中Insert函数无法正常工作。它显示错误消息,如“ExecuteNonQuery需要一个开放且可用的连接。连接的当前状态已关闭。”如果我在第14行删除了Sql Close语句,则显示此错误消息“已经有一个与此命令关联的开放DataReader必须先关闭。“我的代码如下所示。我从产品表中检查了可用的库存。如果数量订单大于“产品表”中的数量,则显示错误消息。否则,继续将订单信息插入销售表。任何帮助表示赞赏。

 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();

        }

    }

2 个答案:

答案 0 :(得分: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 :(得分: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分支中的命令+连接的那个错误。