多次使用SqlCommand时出错

多次使用SqlCommand时出错,sql,database,visual-studio-2012,Sql,Database,Visual Studio 2012,我正在对函数ExecuteOnQuery使用SqlCommand,但它给了我一个错误: 已存在与此命令关联的打开的datareader,必须先关闭该命令 我知道我需要关闭它。所以我使用了dispode方法,但它不起作用。 有人能帮我吗? 谢谢大家! 下面是一些代码: Product pr = new Product(); pr.command.Dispose(); if ((t

我正在对函数ExecuteOnQuery使用SqlCommand,但它给了我一个错误: 已存在与此命令关联的打开的datareader,必须先关闭该命令 我知道我需要关闭它。所以我使用了dispode方法,但它不起作用。 有人能帮我吗? 谢谢大家!

下面是一些代码:

                    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肯定会这样做。