Подтвердить что ты не робот

Исключение: уже есть открытый 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."
        }
    }
}
4b9b3361

Ответ 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
    }
}