c#, я продолжаю ловить исключение нескольких считывателей MySQL, когда есть только 1 читатель

У меня есть приложение Windows Forms на С#, в котором одна из кнопок запускает такой код:

private void aCertainButton_Click(object sender, EventArgs e)
{
    if (folderFinder.ShowDialog() == DialogResult.OK)
    {
        if (openConnection())
        {
            foreach (Thingy stuff in aCertainCollection)
            {
                string sqlCommandString = "SELECT COUNT(*) FROM thatTable WHERE someField = " + stuff.property +  ";";
                try
                {
                    MySqlCommand count = new MySqlCommand(sqlCommandString, connection);
                    int rowCount = 0;
                    object o = count.ExecuteScalar();
                    if (o != null)
                    {
                        rowCount = int.Parse(o.ToString());
                    }

                    if (rowCount == 1)
                    {
                        MySqlCommand cmd = new MySqlCommand("SELECT * FROM thatTable WHERE someField = " + stuff.property +  ";", connection);
                        MySqlDataReader reader = cmd.ExecuteReader();

                        //Processing stuff from the reader here

                        reader.Close();
                        reader.Dispose();
                    }
                }
                catch (MySqlException mex)
                {
                    Console.WriteLine(mex.Message);
                }
            }
            closeConnection();
        }
    }
}

Каждый раз, когда я запускаю приложение, я получаю следующее исключение: «Уже есть открытый DataReader, связанный с этим соединением, которое должно быть закрыто в первую очередь».

Но не должно быть. Я использую 1 считыватель в этом коде, и больше ничего не работает асинхронно. Как видите, я закрываю средство чтения и открываю новое после каждой итерации в цикле. Я использую считыватель, связанный с тем же соединением при инициализации приложения, но когда обработка данных из него завершена, я закрываю его и избавляюсь от него.

Я был бы признателен, если бы кто-нибудь помог мне решить эту загадку, спасибо.


person Zoltán Király    schedule 17.07.2017    source источник
comment
Ваш код потенциально открыт для уязвимостей SQL-инъекций. Пожалуйста, прочитайте и используйте параметризованные запросы.   -  person Daniel Mann    schedule 17.07.2017
comment
Похоже, вы используете глобальное соединение. Возможно ли, что на нем открыто средство чтения до того, как вы нажмете первое в этом коде? Я настоятельно рекомендую создавать соединения по мере необходимости и убедиться, что вы поместили все одноразовые объекты в оператор using. msdn.microsoft.com/en-us/library/   -  person juharr    schedule 17.07.2017
comment
@Daniel Mann Спасибо, но это для небольшого служебного приложения, которое я пишу только для себя. Все абсолютно местное. Я полагаю, что проблема тоже должна быть локальной, а не исходить от злоумышленника.   -  person Zoltán Király    schedule 17.07.2017
comment
@juharr Сначала я тоже так думал, но я просмотрел код, и единственный другой считыватель находится в инициализации, и он правильно закрывается.   -  person Zoltán Király    schedule 17.07.2017
comment
Если что-то генерирует исключение внутри вашей попытки, когда вы обрабатываете материал, вы оставите читатель открытым, и в следующем цикле он будет жаловаться на это.   -  person Gusman    schedule 17.07.2017
comment
Вы не закрываете считыватель, если возникает исключение (поэтому вы должны использовать операторы using), но я предполагаю, что вы не получаете исключение перед тем, что касается нескольких считывателей.   -  person juharr    schedule 17.07.2017
comment
@Gusman, это может происходить, я проверю. Спасибо, отпишусь, если что.   -  person Zoltán Király    schedule 17.07.2017
comment
@ZoltánKirály Мой комментарий был не о вашей текущей проблеме, а о привлечении вашего внимания к невероятно распространенной, невероятно плохой практике, которая приводит к нарушениям безопасности. Даже если это личное приложение, вы должны знать о SQL-инъекциях и способах их предотвращения, а также избавиться от привычки писать код, потенциально подверженный им.   -  person Daniel Mann    schedule 17.07.2017


Ответы (1)


В вашем коде, если что-то генерирует исключение в части, называемой «материал обработки», вы оставите читатель открытым.

Когда вам нужно убедиться, что что-то удалено после его использования даже в случае исключения, используйте пункт using:

if (rowCount == 1)
{
    MySqlCommand cmd = new MySqlCommand("SELECT * FROM thatTable WHERE someField = " + stuff.property +  ";", connection);
    using(MySqlDataReader reader = cmd.ExecuteReader())
    {

        //Processing stuff from the reader here

    }
}
person Gusman    schedule 17.07.2017
comment
Это было именно то, что происходило, ваше решение сработало отлично. Спасибо. - person Zoltán Király; 17.07.2017