Исключение: уже есть открытый DataReader, связанный с этим соединением, который должен быть закрыт первым
У меня есть код ниже, и я получаю исключение:
Существует уже открытый 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."
}
}
}
Ответы
Ответ 1
Вы используете одно и то же соединение для DataReader
и ExecuteNonQuery
. Это не поддерживается, в соответствии с MSDN:
Обратите внимание, что пока DataReader открыт, Connection используется только этим DataReader. Вы не можете выполнять какие-либо команды для Соединения, включая создание другого DataReader, пока исходный DataReader не будет закрыт.
Обновлено 2018: ссылка на MSDN
Ответ 2
Всегда, всегда, всегда ставьте одноразовые объекты внутри использования операторов. Я не вижу, как вы создали экземпляр DataReader, но вы должны сделать это следующим образом:
using (Connection c = ...)
{
using (DataReader dr = ...)
{
//Work with dr in here.
}
}
//Now the connection and reader have been closed and disposed.
Теперь, чтобы ответить на ваш вопрос, читатель использует то же соединение, что и команда, которую вы пытаетесь включить ExecuteNonQuery
. Вам необходимо использовать отдельное соединение, так как DataReader держит соединение открытым и считывает данные по мере необходимости.
Ответ 3
Вы пытаетесь вставить (с ExecuteNonQuery()
) в SQL-соединение, которое уже используется этим читателем:
while (myReader.Read())
Либо сначала прочитайте все значения в списке, закройте читатель, а затем выполните вставку или используйте новое SQL-соединение.
Ответ 4
Проблема, с которой вы работаете, заключается в том, что вы запускаете второй MySqlCommand
, сохраняя при этом данные с помощью DataReader
. Разъем MySQL допускает только один одновременный запрос. Вам нужно прочитать данные в какой-то структуре, затем закройте читатель, а затем обработайте данные. К сожалению, вы не можете обрабатывать данные по мере их чтения, если ваша обработка включает в себя дальнейшие SQL-запросы.
Ответ 5
Вы должны закрыть читателя в дополнение к вашему другому состоянию.
Ответ 6
Просто используйте MultipleActiveResultSets=True
в строке подключения.
Ответ 7
Как заявил Дэвид Суарес, вы пытаетесь читать параллельно.
У меня была та же проблема, и я нашел быстрое и простое решение.
Перед началом чтения прочитайте цикл ожидания
private void WaitForEndOfRead()
{
int count = 0;
while (_connection.State == ConnectionState.Fetching)
{
Thread.Sleep(1000);
count++;
if (count == 10)
{
break;
}
}
}
Затем, прежде чем вы запустите свой SqlCommand, вызовите функцию выше.
Что-то вроде:
using (SqlCommand command = new SqlCommand("GetData", _connection))
{
command.CommandType = CommandType.StoredProcedure;
using (SqlDataReader dr = command.ExecuteReader())
{
// do your thing here
}
}