C# 异常:已存在与此连接关联的打开的DataReader,必须先关闭该连接
我有以下代码,我遇到异常: 已经有一个打开的C# 异常:已存在与此连接关联的打开的DataReader,必须先关闭该连接,c#,mysql,C#,Mysql,我有以下代码,我遇到异常: 已经有一个打开的DataReader与此连接关联,必须先关闭该连接 我正在使用VisualStudio2010/.NET4.0和MySQL来完成这个项目。基本上,我正在尝试运行另一个SQL语句,同时使用data reader执行其他任务。我在第cmdInserttblProductFrance.ExecuteOnQuery()行遇到异常 SQL=“从TBLPProduct中选择*”; //创建连接/命令/MySQLDataReader MySqlConnection
DataReader
与此连接关联,必须先关闭该连接
我正在使用VisualStudio2010/.NET4.0和MySQL来完成这个项目。基本上,我正在尝试运行另一个SQL语句,同时使用data reader执行其他任务。我在第cmdInserttblProductFrance.ExecuteOnQuery()行遇到异常代码>
SQL=“从TBLPProduct中选择*”;
//创建连接/命令/MySQLDataReader
MySqlConnection myConnection=新的MySqlConnection(参见GetConnectionString());
myConnection.Open();
MySqlCommand myCommand=新的MySqlCommand(SQL,myConnection);
MySqlDataReader myReader=myCommand.ExecuteReader();
myCommand.Dispose();
if(myReader.HasRows)
{
int i=0;
//在访问数据之前始终调用Read。
while(myReader.Read())
{
if(myReader[“frProductid”].ToString()==“”)/此项不存在productid
{
strInsertSQL=“插入tblProduct_temp(Productid)值('this istest')”;
MySqlCommand cmdInserttblProductFrance=新的MySqlCommand(strInsertSQL,myConnection);
cmdInserttblProductFrance.ExecuteOnQuery();//始终,始终,始终将一次性对象放在using语句中。我看不出您是如何实例化DataReader的,但您应该这样做:
using (Connection c = ...)
{
using (DataReader dr = ...)
{
//Work with dr in here.
}
}
//Now the connection and reader have been closed and disposed.
现在,为了回答您的问题,读取器使用的连接与您尝试对其执行的命令相同。您需要使用单独的连接,因为DataReader会保持连接打开并根据需要读取数据。您正在尝试插入(使用ExecuteOnQuery()
)在此读取器已使用的SQL连接上:
while (myReader.Read())
首先读取列表中的所有值,关闭读取器,然后进行插入,或者使用新的SQL连接。您遇到的问题是,您正在启动第二个MySqlCommand
,同时仍然使用DataReader
读回数据。MySQL连接器只允许一个并发查询。您需要重新启动将数据放入某种结构中,然后关闭读卡器,然后处理数据。不幸的是,如果处理涉及进一步的SQL查询,则无法在读取时处理数据。您对DataReader
和ExecuteOnQuery
使用相同的连接。这不受支持:
请注意,当DataReader打开时,连接正在使用中
只能由该数据读取器执行。您不能对该数据读取器执行任何命令
连接,包括创建另一个DataReader,直到
原始数据读取器已关闭
更新2018:链接到您必须在else条件之上关闭读卡器。只需在连接字符串中使用MultipleActiveResultSets=True
。如果您没有正确使用事务,也会发生此异常。在我的情况下,我将transaction.Commit()
就在命令.ExecuteReaderAsync()
之后,没有等待事务提交,直到调用reader.ReadAsync()
。正确的顺序:
创建事务
创建阅读器
读取数据
提交事务
将MultipleActiveResultSets=true
添加到连接字符串的提供程序部分
文件appsettings.json中的示例
"ConnectionStrings": {
"EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=YourDatabasename;Trusted_Connection=true;MultipleActiveResultSets=true"}
这就是我要说的,但我正忙着在下面发表评论。该死。不管怎样,是的,这就是答案-使用不同的连接对象。+1对你来说。很好的保存!;-)对你很好。第二部分在我写评论时不在。对不起。是的,我过早地点击了保存。你一定在那3秒钟的窗口中看到了我的答案。我是很多情况下,你真的不想每次都关闭数据库连接。通常情况下,数据库连接应该保持打开状态。通常你有一个线程轮询数据库中的数据,所以一个线程正在这样做,但你也希望程序中的其他线程能够选择或插入内容,所有这些都在同一个数据库连接上……我通常使用自己的线程“包装器”包装连接器,当我将所有行读取到内存中时,我没有一个打开的读取器。这很有趣。在过去10年中,我们打开了一个数据库连接(MySql),并保持它打开,对该连接运行所有查询。我从未遇到过这个错误,直到现在我切换到OrmLite(ServiceStack)。对我来说,这种行为的存在似乎很奇怪:我想打开一次连接,直到应用程序关闭为止。每次我想进行查询时都打开它似乎是一个巨大的开销?@Ted你只是在功能上“打开”和“关闭”从技术上讲,这些调用仅从池中借用和返回连接(假设Pooling=True),它们保持打开状态。这是由ADO.NET管理的,Microsoft的底层框架在此基础上构建了各种连接器。这使生活更加轻松:如果一次只需要一个连接,则池可能只有一个连接。但是,一旦您开始执行并发查询(例如,当读卡器打开时写入),您将根据需要获得多个连接。我看到的错误消息是“…与此命令关联…”,我猜该消息是错误的,这篇文章解释说找不到指向MSDN的链接!
"ConnectionStrings": {
"EmployeeDBConnection": "server=(localdb)\\MSSQLLocalDB;database=YourDatabasename;Trusted_Connection=true;MultipleActiveResultSets=true"}