【问题标题】:There is already an open DataReader associated with this Command which must be closed first error已经有一个与此命令关联的打开的 DataReader 必须先关闭错误
【发布时间】:2015-05-02 03:19:23
【问题描述】:

我在asp.net 中有两个gridviews 使用Ajax 的标签容器分隔。在一个按钮单击事件中,我希望使用来自两个不同存储过程的数据源填充两个网格视图。

第一个网格视图 - 每个租户的销售详细摘要

第二个网格视图 - 每个日期的合并销售组

这是代码

        SqlCommand cmd = new SqlCommand("spDSRDetailed", con);
        cmd.CommandTimeout = 120;
        cmd.CommandType = System.Data.CommandType.StoredProcedure;

        cmd.Parameters.AddWithValue("@dateFrom", txtdatefrom.Text);
        cmd.Parameters.AddWithValue("@dateTo", txtdateto.Text);
        cmd.Parameters.AddWithValue("@Location", hdnLoc.Value);
        cmd.Parameters.AddWithValue("@RP", hdnRP.Value);

        try
        {
            con.Open();
            grdDailySalesReport.EmptyDataText = "No Records Found";
            grdDailySalesReport.DataSource = cmd.ExecuteReader();
            grdDailySalesReport.DataBind();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            con.Close();
            con.Dispose();
        }

此代码仅适用于一个 gridview,我知道可以使用 SQLDatasource 执行此操作,但该方法不是我的选择,因为我使用了复杂的 SQL 查询,而不适合使用 SQLDATASOURCE.SELECTCOMMAND 执行此操作。

我试过了,它给了我这个错误

已经有一个打开的 DataReader 与此命令关联,必须先关闭。

        SqlCommand cmd = new SqlCommand("spDSRDetailed", con);
        cmd.CommandTimeout = 120;
        cmd.CommandType = System.Data.CommandType.StoredProcedure;

        SqlCommand cmd2 = new SqlCommand("spDSRConso", con);
        cmd2.CommandTimeout = 120;
        cmd2.CommandType = System.Data.CommandType.StoredProcedure;


        cmd.Parameters.AddWithValue("@dateFrom", txtdatefrom.Text);
        cmd.Parameters.AddWithValue("@dateTo", txtdateto.Text);
        cmd.Parameters.AddWithValue("@Location", hdnLoc.Value);
        cmd.Parameters.AddWithValue("@RP", hdnRP.Value);

        cmd2.Parameters.AddWithValue("@dateFrom", txtdatefrom.Text);
        cmd2.Parameters.AddWithValue("@dateTo", txtdateto.Text);
        cmd2.Parameters.AddWithValue("@Location", hdnLoc.Value);
        cmd2.Parameters.AddWithValue("@RP", hdnRP.Value);


        try
        {
            con.Open();
            grdDailySalesReport.EmptyDataText = "No Records Found";
            grdDailySalesReport.DataSource = cmd.ExecuteReader();
            grdDailySalesReport.DataBind();


            grdDSRConso.EmptyDataText = "No Records Found";
            grdDSRConso.DataSource = cmd2.ExecuteReader();
            grdDSRConso.DataBind();
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            con.Close();
            con.Dispose();
        }

【问题讨论】:

  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 好的。著名的。谢谢你:)
  • 嗨@John,可以将我的问题的标题更改为:已经有一个打开的 DataReader 与此命令关联,必须先关闭。 (实际错误)
  • 当然可以,但是应该省略“in ASP.NET C#”部分。它甚至不相关。
  • web.config 文件中有一个customErrors 部分,它允许使用漂亮的错误页面。不要太担心应用程序失败时的外观 - 而要担心修复应用程序并尽你所能确保将来不会发生问题。

标签: c# asp.net sql-server stored-procedures gridview


【解决方案1】:

您正在使用SqlCommand.ExecuteReader 并且消息说:

已经有一个打开的 DataReader 与此命令关联 必须先关闭

所以你需要先关闭第一个SqlCommand.ExecuteReader

试试这个:

SqlDataReader reader = cmd.ExecuteReader();
grdDailySalesReport.EmptyDataText = "No Records Found";
grdDailySalesReport.DataSource = reader;
grdDailySalesReport.DataBind();

reader.Close();

reader = cmd2.ExecuteReader();
grdDSRConso.EmptyDataText = "No Records Found";
grdDSRConso.DataSource = reader;
grdDSRConso.DataBind();

reader.Close();

【讨论】:

  • 更好的是,SqlCommandSqlDataReaders 和 SqlConnection 都需要在 using 块中。
  • 嗨@Iswanto,谢谢它的工作!多谢。您认为我在性能/速度方面使用了最佳方法,还是有任何替代方法可以满足我的要求?
  • 无论如何我会接受你的回答,但如果有人可以说它在速度方面更好,我会接受:) 非常感谢@Iswanto 的帮助。上帝保佑你
  • @rickyProgrammer 以获得您想要对所有 using 块使用的最佳性能 SqlConnections 并使它们尽可能小。 .NET 使用connection pooling,因此当您退出 using 块时,它实际上并没有关闭连接,而是将其返回到池中。这让代码的其他部分可以重用连接,而不会产生启动连接的开销。
  • @ScottChamberlain:更重要的是,using 块确保其中的对象及时清理,即使抛出异常也是如此。它应该用于实现IDisposable 接口的所有对象,在本例中为SqlCommandSqlDataReaders 和SqlConnection
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
相关资源
最近更新 更多