【问题标题】:Invalid attempt to call Read when reader is closed?阅读器关闭时尝试调用读取无效?
【发布时间】:2011-08-26 15:29:24
【问题描述】:

我在查询中运行DbDataReader 以从下拉列表中删除已附加到特定提交的项目,并且我不断收到错误消息,告诉我阅读器已关闭。不明白为什么我的读者在这里被视为关闭。我错过了什么?

 protected void Page_Load(object sender, EventArgs e)
{

    string x = Request.QueryString["SubId"];
    string connectionString = System.Configuration.ConfigurationManager.
        ConnectionStrings["MyConnectionString"].ConnectionString;
    string displayQuery = "SELECT CustName, CustAdd, CustCity, CustState, " +
        "CustZip FROM Customer WHERE SubId =" + x;
    string broQuery = "SELECT EntityType FROM Broker WHERE SubId =" + x;
    string ddlQuery = "SELECT ProductId FROM SubmissionProducts " +
        "WHERE SubmissionId =" + x;
    using (SqlConnection displayConn = new SqlConnection(connectionString))
    {
        displayConn.Open();
        SqlCommand DlistCmd = new SqlCommand(ddlQuery, displayConn);

        using (SqlDataReader Ddldr = DlistCmd.ExecuteReader())
        {
            while (Ddldr.Read())
            {

                switch (Ddldr.GetInt32(0))
                {
                    case 1:
                        DdlProductList.Items.RemoveAt(1);
                        break;
                    case 2:
                        DdlProductList.Items.RemoveAt(2);
                        break;
                    case 3:
                        DdlProductList.Items.RemoveAt(3);
                        break;
                    case 4:
                        DdlProductList.Items.RemoveAt(4);
                        break;
                    case 5:
                        DdlProductList.Items.RemoveAt(5);
                        break;
                    case 6:
                        DdlProductList.Items.RemoveAt(6);
                        break;
                    case 7:
                        DdlProductList.Items.RemoveAt(7);
                        break;
                    default:
                        break;
                }
                Ddldr.Close();
            }

        }

【问题讨论】:

  • 这只是一个猜测,但你的意思是在这里执行 DDL 命令吗?
  • @Adrian:这就是using....的用途...
  • @Gabriel 我认为他在这里使用 DDL 来表示“DropdownList”,即他页面上的 ASP.NET 控件。
  • 也许你可以发布更多的代码?
  • 因此,如果您从头开始提供所有代码 - 您将在几分钟内得到正确答案。

标签: c# asp.net sql-server visual-studio


【解决方案1】:

不要打电话给Ddldr.Close();,尤其是在while内部。这样,您将进行第一次迭代,关闭阅读器,第二次迭代当然会随着阅读器的关闭而繁荣。 using 语句将处理它。只需从您的代码中删除这一行。

所以:

using (SqlDataReader Ddldr = DlistCmd.ExecuteReader())
{
    while (Ddldr.Read())
    {
        switch (Ddldr.GetInt32(0))
        {
            ... your cases here
            default:
                break;
        }
    }
}

还有以下几行:

string x = Request.QueryString["SubId"];
string displayQuery = "SELECT CustName, CustAdd, CustCity, CustState, CustZip FROM Customer WHERE SubId =" + x;
string broQuery = "SELECT EntityType FROM Broker WHERE SubId =" + x;
string ddlQuery = "SELECT ProductId FROM SubmissionProducts WHERE SubmissionId =" + x;

臭得像一堆垃圾。您应该使用参数化查询并且绝对不要编写任何这样的代码,否则您的应用程序将容易受到 SQL 注入的攻击。每次您在编写 SQL 查询时使用字符串连接时,都会响起警报,告诉您您做错了。

所以正确的做法来了:

protected void Page_Load(object sender, EventArgs e)
{
    string x = Request.QueryString["SubId"];
    string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
    using (var conn = new SqlConnection(connectionString))
    using (var cmd = conn.CreateCommand())
    {
        conn.Open();
        cmd.CommandText = "SELECT ProductId FROM SubmissionProducts WHERE SubmissionId = @SubmissionId";
        cmd.Parameters.AddWithValue("@SubmissionId", x)

        using (var reader = cmd.ExecuteReader())
        {
            while (Ddldr.Read())
            {
                switch (reader.GetInt32(reader.GetOrdinal("ProductId")))
                {
                    ... your cases here
                    default:
                        break;
                }
            }

        }
    }
}

【讨论】:

  • 谢谢你,达林。我需要了解执行迭代的方式,以认识到 dr.close 语句必须执行。这是我第一次使用编码,我的培训师为了简单起见特别禁止我进行参数化(该站点不适用于实际部署),但是是的,我同意,未参数化的查询正在乞求注入。
【解决方案2】:

删除这一行:

Ddldr.Close();

【讨论】:

  • 哈哈,当我生命中的两个小时减少到 14 个错误代码字符时,我一定会喜欢它。谢谢霍根。
  • @Brazos -- 是的,这很痛苦。但每次发生在我身上时,我都会为“我不会再那样做”而欢呼。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多