例外:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭

Posted

技术标签:

【中文标题】例外:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭【英文标题】:Exception: There is already an open DataReader associated with this Connection which must be closed first 【发布时间】: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 相关联...',我猜这个信息是错误的,这篇文章解释了 【参考方案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() 才等待事务提交。正确的顺序:

    创建事务。 创建阅读器。 读取数据。 提交事务。

【讨论】:

【参考方案8】:

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

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

【讨论】:

以上是关于例外:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭的主要内容,如果未能解决你的问题,请参考以下文章

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

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

调用另一个 repo 时出错 - '已经有一个打开的 DataReader 与此命令关联,必须先关闭'

已经有一个与此命令关联的打开的 DataReader 必须首先关闭 linq [重复]

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

错误:已经有一个与此命令关联的打开DataReader,必须先关闭它。多个用户