例外:已经有一个打开的 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】:您对DataReader
和ExecuteNonQuery
使用相同的连接。这个不支持,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 [重复]