多次使用SqlCommand时出错
我正在对函数ExecuteOnQuery使用SqlCommand,但它给了我一个错误: 已存在与此命令关联的打开的datareader,必须先关闭该命令 我知道我需要关闭它。所以我使用了dispode方法,但它不起作用。 有人能帮我吗? 谢谢大家! 下面是一些代码:多次使用SqlCommand时出错,sql,database,visual-studio-2012,Sql,Database,Visual Studio 2012,我正在对函数ExecuteOnQuery使用SqlCommand,但它给了我一个错误: 已存在与此命令关联的打开的datareader,必须先关闭该命令 我知道我需要关闭它。所以我使用了dispode方法,但它不起作用。 有人能帮我吗? 谢谢大家! 下面是一些代码: Product pr = new Product(); pr.command.Dispose(); if ((t
Product pr = new Product();
pr.command.Dispose();
if ((t=(search(int.Parse(CatNum.Text))))!=null)
{
if (t == "Float")
{
pr.command.Dispose();
pr.command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
SqlDataReader reader = pr.command.ExecuteReader();
float currAmount = 0;
while (reader.Read())
{
currAmount = float.Parse(reader["amount"].ToString());
}
pr.command.CommandText = string.Format("Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}", int.Parse(CatNum.Text), float.Parse(Amount.Text) + currAmount);
pr.command.ExecuteNonQuery();
CatNum.Text = string.Empty;
CatNum.Focus();
sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
}
else if (int.TryParse(Amount.Text, out q) && t == "Integer")
{
pr.command.Dispose();
pr.command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
SqlDataReader reader = pr.command.ExecuteReader();
int currAmount = 0;
while (reader.Read())
{
currAmount = int.Parse(reader["amount"].ToString());
}
pr.command.CommandText = string.Format("Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}", int.Parse(CatNum.Text), int.Parse(Amount.Text) + currAmount);
pr.command.ExecuteNonQuery();
CatNum.Text = string.Empty;
CatNum.Focus();
sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
}
在开始第二个查询之前添加此项
读者。关闭 您应该使用try-catch-finally异常管理,以避免代码中未处理的异常 如果命令失败,或者是因为连接断开,或者仅仅是因为查询不正确,那么读取器将不会关闭,因为它无法到达代码的该部分 尝试将您的代码如下所示:
Product pr = new Product();
try {
pr.command.Dispose();
if ((t=(search(int.Parse(CatNum.Text))))!=null)
{
if (t == "Float")
{
pr.command.Dispose();
pr.command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
SqlDataReader reader = pr.command.ExecuteReader();
float currAmount = 0;
while (reader.Read())
{
currAmount = float.Parse(reader["amount"].ToString());
}
reader.close;
pr.command.CommandText = string.Format("Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}", int.Parse(CatNum.Text), float.Parse(Amount.Text) + currAmount);
pr.command.ExecuteNonQuery();
CatNum.Text = string.Empty;
CatNum.Focus();
sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
}
else if (int.TryParse(Amount.Text, out q) && t == "Integer")
{
pr.command.Dispose();
pr.command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
SqlDataReader reader = pr.command.ExecuteReader();
int currAmount = 0;
while (reader.Read())
{
currAmount = int.Parse(reader["amount"].ToString());
}
reader.close;
pr.command.CommandText = string.Format("Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}", int.Parse(CatNum.Text), int.Parse(Amount.Text) + currAmount);
pr.command.ExecuteNonQuery();
CatNum.Text = string.Empty;
CatNum.Focus();
sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
}
}
catch (SqlException sqlex) {
// do your thing when sql exception pops out }
catch (Exception ex) {
// do your thing when any exception pops out }
finally {
reader.close; }
这将关闭读卡器,即使出现异常。这段代码有太多问题,我真的不知道从哪里开始 在不使任何事情过于复杂化并尽可能保持通用性的情况下,我建议取消您的产品类,它看起来就像是SqlCommand的持有者,并且根据您的使用情况,这并不是很有帮助,甚至没有考虑这种方法的问题 如果每次都使用新的SqlCommand和connection,效果会好得多,它实际上没有那么多代码:
using (var connection = new SqlConnection("YourConnectionString"))
using (var command = new SqlCommand("CommandText", connection))
{
connection.Open();
// User your command here
}
接下来,不要使用string.Format来构建查询,使用适当的参数化查询,您将受益于类型安全和查询计划缓存,并消除sql注入的风险
所以不是
command.CommandText = string.Format("select amount from storage where catalogNumber={0}", int.Parse(CatNum.Text));
您可以使用:
command.CommandText = "SELECT Amount FROM Storage WHERE CatalogNumber = @CatalogNumber";
int catNum = 0;
if (!int.TryParse(CatNum.Text, out catNum))
{
// Do something to handle an invalid input
}
command.Parameters.AddWithValue("@CatalogNumber", catNum);
下一个问题是:
while (reader.Read())
{
currAmount = float.Parse(reader["amount"].ToString());
}
这里有两个问题,第一个是不必要的强制转换,您可以只使用reader.GetFloat,但更重要的是,您将迭代整个数据集,只将最后一行中的值分配给变量。如果您的数据集只有一行,那么这不是一个真正的问题,但您也可以使用ExecuteScalar来获取单个值
currAmount = float.Parse(command.ExecuteScalar().ToString());
最后,在此更新中,您实际上没有执行任何操作:
Update storage set catalogNumber={0} amount = {1} where catalogNumber={0}
您刚刚从同一个表中读取了amount,并将CatalogNumber设置为1,其中CatalogNumber=1不起任何作用
我真的不明白为什么要在两个单独的块中处理浮点和整数,但看起来您的代码可以简化为:
int catNum = 0;
if (!int.TryParse(CatNum.Text, out catNum))
{
// Do something to handle an invalid input
}
float currAmount = 0;
using (var connection = new SqlConnection("YourConnectionString"))
using (var command = new SqlCommand("SELECT Amount FROM Storage WHERE CatalogNumber = @CatalogNumber", connection))
{
command.Parameters.AddWithValue("@CatalogNumber", catNum);
connection.Open();
currAmount = float.Parse(command.ExecuteScalar().ToString());
}
CatNum.Text = string.Empty;
CatNum.Focus();
sb.AppendFormat("<div class='alert alert-success'>Adding the product was successfull</div>");
不要重复使用该命令,使用新连接启动一个新命令。NET做它自己的连接池,所以你不能通过重用对象得到任何东西;在尝试重新使用SqlCommand对象之前,但没有看到您的代码,这只是猜测。您是否在while循环后将代码放入我的答案中?SqlCommand对象可能不可用。但是SqlDataReader肯定会这样做。