Неустранимая ошибка при использовании MySqlDataReader

Я получаю следующую ошибку в моем приложении C# WinForms:

фатальная ошибка при чтении данных

Я использую mysql.data V4.0.30319.

Вот мой код:

int catCount = 1;     
while (catCount < 13)
{
    MySqlConnection con = new MySqlConnection("server=server;user id=user;password=password;database=db;");
    con.Open();
    MySqlDataReader Rd;
    string query = "SELECT oc_newsletter_old_system.email FROM oc_newsletter_old_system WHERE oc_newsletter_old_system.cat_uid = "  + catCount;
    MySqlCommand mC = new MySqlCommand(query, con);
    Rd = mC.ExecuteReader();
    try
    {      
        while (Rd.Read())
        {
            string email = Rd.GetString(0);
            Boolean insert = true;
            int realCat = 0;
            switch (catCount)
            {
                case '1':
                    fileBrian += email + "\r\n";
                    break;
                case '2':
                    fileDunamis += email + "\r\n";
                    break;
                case '3':
                    fileFrohlich += email + "\r\n";
                    break;
                case '4':
                    fileGaithers += email + "\r\n";
                    break;
                case '5':
                    fileGospel7 += email + "\r\n";
                    break;
                case '6':
                    fileLifeshop += email + "\r\n";
                    realCat = 1;
                    break;
                case '7':
                    fileMeyer += email + "\r\n";
                    break;
                case '8':
                    fileOpwekking += email + "\r\n";
                    break;
                case '9':
                    filePelgrimKerken += email + "\r\n";
                    realCat = 2;
                    break;
                case 10:
                    filePelgrimKlanten += email + "\r\n";
                    realCat = 2;
                    break;
                case 11:
                    filePelgrimPers += email + "\r\n";
                    insert = false;
                    break;
                case 12:
                    filePelgrimScholen += email + "\r\n";
                    insert = false;
                    break;
            }

            if (insert == true)
            {    
                string salt = "h1bsqnp6wyxjxhf29ziuwsihg8nixe05";
                byte[] asciiBytes = ASCIIEncoding.ASCII.GetBytes(salt + email);
                byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
                string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
                string query2 = "INSERT IGNORE INTO `oc_ne_marketing` (`email`,`code`, `subscribed`, `store_id`) VALUES ('" + email + "', '" + hashedString + "', '1', '" + realCat + "')";
                MySqlConnection connection = new MySqlConnection("server=server;user id=user;password=password;database=db;");
                connection.Open();
                try
                {
                    MySqlCommand cmd1 = new MySqlCommand(query2, connection);
                    cmd1.CommandText = query2;
                    cmd1.ExecuteNonQuery();
                    cmd1.Dispose();
                }
                finally
                {
                    connection.Close();
                }
            }
            Application.DoEvents();
        }
    }
    finally
    {
        Rd.Close();
        con.Close();
    }

    catCount++;
    progressBar1.PerformStep();
    progressBar1.Refresh();
    Application.DoEvents();
}

Я получаю ошибку в этой строке:

while (Rd.Read())

Единственное, что я обнаружил до сих пор, это проблема с закрытием ридера и подключением, но насколько я знаю, что все настроено правильно...

Так вы, ребята, поняли, в чем дело???


person Mathlight    schedule 31.07.2013    source источник
comment
Можете ли вы попробовать параметризованные запросы?   -  person nawfal    schedule 01.08.2013
comment
@nawfal, я могу попробовать, но я не думаю, что это необходимо ... Первый запрос принимает только целые числа, а второй принимает только сохраненные (уже в БД) данные. Также проблема в ридере. Так вы действительно думаете, что это решит проблему???   -  person Mathlight    schedule 01.08.2013
comment
Поищите в гугле эту проблему. Это дает некоторые результаты. Похоже на ошибку. действительно странно. См. bugs.mysql.com/bug.php?id=61807 stackoverflow.com/questions/ 2546115/ stackoverflow.com/ вопросы/11131429/   -  person nawfal    schedule 01.08.2013
comment
Почему вы используете блоки try без улова? Поместите блок catch в свой try/finally и посмотрите, раскрывает ли он какую-либо дополнительную информацию.   -  person Tim    schedule 01.08.2013
comment
@ Тим, я использую это, чтобы всегда все закрывать, даже когда случается ошибка. И это внутри другой попытки с уловом, и это дает эту ошибку.   -  person Mathlight    schedule 01.08.2013
comment
@Mathlight — используйте блоки using вместо try/finally — они очистят ресурсы, даже если возникнет исключение.   -  person Tim    schedule 01.08.2013
comment
@ Тим, не мог бы ты ответить на это (с кодом)? Я довольно новичок в этом...   -  person Mathlight    schedule 01.08.2013
comment
Конечно... дай мне несколько минут.   -  person Tim    schedule 01.08.2013
comment
@nawfal, спасибо за ссылку на ошибку. Я пробую обходной путь, который они предоставили. Возвращайся через 10 минут...   -  person Mathlight    schedule 01.08.2013
comment
@nawfal, похоже, обходной путь в той ссылке на ошибку, которую вы предоставили, помог. Если вы можете дать ответ на него, я могу принять его. "The workaround then was to customize the net_xxx_timeout settings. For example, issue the following after openning your connection and before executing the datareader: MySqlCommand cmd = new MySqlCommand( "set net_write_timeout=99999; set net_read_timeout=99999", con ); cmd.ExecuteNonQuery(); "   -  person Mathlight    schedule 01.08.2013
comment
@Mathlight Я ответил, но я проголосую за то, чтобы закрыть это как дубликат.   -  person nawfal    schedule 01.08.2013
comment
@nawfal, правила есть правила ;)   -  person Mathlight    schedule 01.08.2013


Ответы (2)


A2A, для полноты картины.

Из здесь:

Тогда обходной путь состоял в том, чтобы настроить параметры net_xxx_timeout. Например, выполните следующее после открытия соединения и перед выполнением средства чтения данных:

var c = new MySqlCommand("set net_write_timeout=99999; set net_read_timeout=99999", con);
c.ExecuteNonQuery();

Вот исходник из MySql.Data в классе подключения:

protected override void Dispose(bool disposing)
{
  if (State == ConnectionState.Open)
    Close();
  base.Dispose(disposing);
}

что в основном означает, что достаточно избавиться от него, чтобы закрыть его (иначе это странно). То же самое относится и к SqlConnection ..

person nawfal    schedule 31.07.2013

Хотя это и не прямой ответ на вашу проблему, по вашему запросу вот некоторая информация и пример кода на using.

Общепринятой наилучшей практикой является использование операторов using с объектами, которые реализуют IDisposable - по сути, это делает то же самое, что и блок try/finally.

После выхода из области использования оператора (либо операция завершается, либо генерируется исключение), Dispose будет вызываться для объекта. Дополнительные сведения см. в разделе использование Заявления.

Вот сокращенный пример, основанный на вашем коде:

int catCount = 1;     
string connectionString = "server=server;user id=user;password=password;database=db;"
string query = "SELECT email FROM oc_newsletter_old_system WHERE cat_uid=@cat_uid";

while (catCount < 13)
{

    using (MySqlConnection con = new MySqlConnection(connectionString))
    {

        con.Open();

        MySqlCommand mC = new MySqlCommand(query, con);
        mC.Parameters.AddWithValue("@cat_uid", catCount);

        using (MySqlDataReader Rd = mC.ExecuteReader())
        {

            while (Rd.Read())
            {

                 // rest of your code here
            }
        }
    }    
}

Обратите внимание, что приведенное выше основано на классах .NET SqlConnection, SqlCommand и SqlDataReader, но должно быть таким же (или очень похожим) для MySql.

Я переместил строку подключения и строку запроса в их собственные переменные (но это личное предпочтение). Я также привел пример того, как выполнять параметризованные запросы (строка mCParameters.AddWithValue - привычка использовать параметризованные запросы - это (IMO) хорошая вещь, особенно если вы переходите с WinForms на веб-приложения, поскольку это предотвращает атаки SQL Injection. .

person Tim    schedule 31.07.2013
comment
Спасибо за объяснение. Но 1 вещь о связи. Говорят, что вы должны закрыть вместо (или поверх) dispose. Где тогда закрыть соединение (даже при возникновении исключения) - person Mathlight; 01.08.2013
comment
Где ты это увидел? Я ожидаю, что правильно реализованный Dispose закроет существующее соединение - я никогда явно не закрывал SqlConnection. Возможно, это что-то уникальное для MySql? - person Tim; 01.08.2013
comment
См. этот ответ SO. Dispose закрывает SqlConnection: stackoverflow.com/a/1195854/745969 Опять же, MySql может это делать иначе. - person Tim; 01.08.2013
comment
Это как-то связано с пулом соединений. это документация, где ментоид здесь, в комментариях "It then releases the connection to the connection pool, or closes the connection if connection pooling is disabled." So Close() should be sufficient to keep the connection pool from overflowing - person Mathlight; 01.08.2013
comment
@Mathlight Я давно использую MySQL, вам не нужно удалять или закрывать. Просто заверните его в пункт using, этого достаточно.. - person nawfal; 01.08.2013
comment
@nawfal, тогда хорошо. С этого момента я буду стараться всегда использовать using. Спасибо большое Тим ;) - person Mathlight; 01.08.2013