我创建了一个销售表,其中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();
}
}
答案 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分支中的命令+连接的那个错误。