【问题标题】:Exception: There is already an open DataReader associated with this Connection which must be closed first例外:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭
【发布时间】:2011-07-23 08:21:05
【问题描述】:

我有以下代码,但遇到异常:

已经有一个打开的DataReader 与这个Connection 关联,必须先关闭它。

我在这个项目中使用 Visual Studio 2010/.Net 4.0 和 MySQL。基本上,我试图在使用数据阅读器执行其他任务时运行另一个 SQL 语句。我在cmdInserttblProductFrance.ExecuteNonQuery(); 行遇到异常情况@

SQL = "Select * from tblProduct";

//Create Connection/Command/MySQLDataReader
MySqlConnection myConnection = new MySqlConnection(cf.GetConnectionString());
myConnection.Open();
MySqlCommand myCommand = new MySqlCommand(SQL, myConnection);
MySqlDataReader myReader = myCommand.ExecuteReader();
myCommand.Dispose();

if (myReader.HasRows)
{
    int i = 0;
    // Always call Read before accessing data.
    while (myReader.Read())
    {
        if (myReader["frProductid"].ToString() == "") //there is no productid exist for this item
        {
            strInsertSQL = "Insert Into tblProduct_temp (Productid) Values('this istest') ";
            MySqlCommand cmdInserttblProductFrance = new MySqlCommand(strInsertSQL, myConnection);
            cmdInserttblProductFrance.ExecuteNonQuery(); //<=====THIS LINE THROWS "C# mySQL There is already an open DataReader associated with this Connection which must be closed first."
        }
    }
}

【问题讨论】:

  • 我看到的错误信息是 '... 与这个 command 相关联...',我猜这个信息是错误的,这篇文章解释了

标签: c# mysql


【解决方案1】:

总是,总是,总是将一次性对象放在 using 语句中。我看不到您是如何实例化 DataReader 的,但您应该这样做:

using (Connection c = ...)
{
    using (DataReader dr = ...)
    {
        //Work with dr in here.
    }
}
//Now the connection and reader have been closed and disposed.

现在,为了回答您的问题,读者正在使用与您尝试ExecuteNonQuery on 的命令相同的连接。您需要使用单独的连接,因为 DataReader 会保持连接打开并根据需要读取数据。

【讨论】:

  • 不错的保存! ;-) 对你有益。当我写评论时,第二部分不在那里。对不起。
  • 是的,我过早地点击了保存,你一定在这 3 秒的窗口中看到了我的答案。
  • 在很多情况下,你真的不想每次都关闭数据库连接。通常,数据库连接应保持打开状态。通常你有一个线程来轮询数据库中的数据,所以一个线程正在这样做,但你还希望程序中的其他线程能够选择或插入东西,所有这些都在同一个数据库连接上......我通常使用我自己的包装连接器的“包装器”,然后当我将所有行读入内存时,我没有打开的阅读器。
  • 这很有趣。在过去的 10 年中,我们打开了一个数据库连接(MySql),并保持打开状态,针对该连接运行所有查询。我从来没有遇到过这个错误,直到现在我切换到 OrmLite (ServiceStack)。对我来说,这种行为的存在似乎很奇怪:我想打开一次连接,并使用它直到应用程序关闭。每次我想要查询时都打开它似乎是一个巨大的开销?
  • @Ted 你只是功能上“打开”和“关闭”它们。从技术上讲,这些调用只是从池中借用和返回连接(假设 Pooling=True),这些连接保持打开状态。这是由 Microsoft 的底层框架 ADO.NET 管理的,在此基础上构建了各种连接器。这让生活变得更加轻松:如果确实一次只需要一个连接,那么池很可能只有一个连接。但是,一旦您开始执行并发查询(例如,在阅读器打开时写入),您将根据需要获得多个连接。
【解决方案2】:

您正在尝试在此阅读器已使用的 SQL 连接上插入(使用ExecuteNonQuery()):

while (myReader.Read())

要么先读取列表中的所有值,然后关闭读取器然后插入,要么使用新的 SQL 连接。

【讨论】:

  • 这就是我要说的,但我正忙着在下面发表评论。该死。无论如何,是的,这就是答案 - 使用不同的连接对象。 +1 给你。
【解决方案3】:

您遇到的问题是您正在启动第二个MySqlCommand,同时仍在使用DataReader 读回数据。 MySQL 连接器只允许一个并发查询。您需要将数据读入某种结构,然后关闭阅读器,然后处理数据。不幸的是,如果您的处理涉及进一步的 SQL 查询,您将无法处理读取的数据。

【讨论】:

    【解决方案4】:

    您对DataReaderExecuteNonQuery 使用相同的连接。这个不支持,according to MSDN:

    请注意,当 DataReader 打开时,连接正在使用中 由该 DataReader 独家提供。您不能执行任何命令 连接,包括创建另一个 DataReader,直到 原始 DataReader 已关闭。

    2018 年更新:链接到MSDN

    【讨论】:

    • 找不到MSDN的链接!
    【解决方案5】:

    您必须在 else 条件之上关闭阅读器。

    【讨论】:

      【解决方案6】:

      只需在连接字符串中使用MultipleActiveResultSets=True

      【讨论】:

      • System.ArgumentException:不支持选项 - 使用 Visual Studio 2019
      • MultipleActiveResultSets 不是 MySQL .Net 连接器 ConnectionString 选项
      【解决方案7】:

      如果您没有正确使用事务,也会发生此异常。就我而言,我将transaction.Commit() 放在command.ExecuteReaderAsync() 之后,直到调用reader.ReadAsync() 才等待事务提交。正确的顺序:

      1. 创建事务。
      2. 创建阅读器。
      3. 读取数据。
      4. 提交事务。

      【讨论】:

        【解决方案8】:

        MultipleActiveResultSets=true 添加到连接字符串的提供者部分 文件 appsettings.json 中的示例

        "ConnectionStrings": {
        "EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=YourDatabasename;Trusted_Connection=true;MultipleActiveResultSets=true"}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-01-17
          • 2020-09-25
          • 2011-12-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多