【问题标题】:C# ExecuteReader requires an open and available Connection. The connection's current state is closedC# ExecuteReader 需要一个打开且可用的连接。连接的当前状态为关闭
【发布时间】:2020-05-14 12:18:20
【问题描述】:
private void comT_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (comT.SelectedIndex != -1)
        {
            SqlCommand cmd = new SqlCommand(@"SELECT ISNULL(substring(MAX(tCode),3,2),'00')
            FROM Teacher
            WHERE dCode = '" + comT.SelectedValue.ToString() + "'", MUControlClass.con);
            SqlDataReader dr = cmd.ExecuteReader();
            dr.Read();  <--HERE IS ERROR **"ExecuteReader requires an open and available Connection. The connection's current state is closed."**
            if (dr[0].ToString() != "00")
            {
                int dugaar = Convert.ToInt32(dr[0]) + 1;
                if (dugaar > 9)
                {
                    msk.Text = comT.SelectedValue.ToString() + dugaar.ToString();
                }
                else
                    msk.Text = comT.SelectedValue.ToString() + "0" + dugaar.ToString();
            }
            else
            {
                msk.Text = comT.SelectedValue.ToString() + "01";
            }
            dr.Close();
        }
    }

ExecuteReader 需要一个打开且可用的连接。连接的当前状态为关闭。错误

【问题讨论】:

  • 错误信息非常清楚。 MUControlClass.con 未打开。
  • 您可能应该使用using {...} 块进行查询调用,并在这样做时始终创建新连接。有关示例,请参见 in a “using” block is a SqlConnection closed on return or exception?
  • 这看起来很可疑,就像您正在尝试跨多个方法共享单个连接对象。这通常是错误的做法。共享连接 string 但不共享连接对象。而是创建接近使用的对象。

标签: c#


【解决方案1】:

立即错误是连接没有打开,正如它告诉你的那样;所以... 打开它;然而,这里还有 很多 其他严重问题 - 最明显的是“SQL 注入”,还有未处置的对象。您可以通过使用参数来修复 SQL 注入,以及大量 using 的未处理问题,但是:我强烈建议您使用默认情况下可以帮助您解决此问题的工具。例如:

private void comT_SelectedIndexChanged(object sender, EventArgs e)
{
    if (comT.SelectedIndex != -1)
    {
        using (var conn = new SqlConnection(yourConnectionString))
        {
            string max = conn.QuerySingle<string>(@"
SELECT ISNULL(substring(MAX(tCode),3,2),'00')
FROM Teacher
WHERE dCode = @dCode", new { dCode = comT.SelectedValue.ToString() });
            if (max != null)
            {
                // your parse/etc logic
            }
        }
    }
}

这是:

  • 将我们的连接生命周期移动到此方法的本地,这将停止很多连接使用问题
  • 使用"Dapper" 提供QuerySingle&lt;T&gt; 代码
  • 这意味着您不需要需要弄乱命令或阅读器
  • 通过@dCodenew { dCode = ... } 用法添加参数用法

请注意,它可能看起来好像我们还没有在此处打开连接,但 Dapper 很乐意为我们这样做;如果给定一个关闭的连接,它只在查询期间打开连接

【讨论】:

  • 我使用存储过程的原因之一。它强制开发者使用参数。
  • @jscarle 我见过人们这样做cmd.CommandText = "EXEC myProc @id=" + id + ", @name='" + name + "'"; - 永远不要低估搞砸的能力;广泛(但不完全)相关:blog.marcgravell.com/2017/12/…
  • @jscarle 更不用说接受参数的存储过程,而是在内部使用它来使用字符串连接创建动态 SQL 语句......Here's an example
【解决方案2】:

无论在MUControlClass 的何处创建连接,您都需要调用con.Open()

【讨论】:

    【解决方案3】:

    您的连接未打开。

    与数据库的连接和交互的简化流程是这样的:

    using(SqlConnection con = new SqlConnection(yourConnectionString))
    {
        con.Open() // You do not open this one so it returns that error
        using(SqlCommand cmd = new SqlCommand(yourSqlCommand, con))
        {
            using(SqlDataReader dr = cmd.ExecuteReader())
            {
                if(dr.Read())
                {
                    // Do something
                }
            }
        }
    }
    

    只要包裹在using 中,我们就不需要关闭/销毁任何东西,因为它们都实现了IDisposable

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      相关资源
      最近更新 更多