connection must be valid and open

И снова привет. Мой прошлый вопрос был построен некорректно, как возможно и этот. Не кидайтесь помидорами, пожалуйста. Я только начал изучать Сишарп и впервые открыл для себя стаковерфлоу. Я думаю будет лучше, если вы объясните, что я как-то не так задал вопрос или что-то не докинул. Спасибо.

var database = new MySqlConnectionStringBuilder(@ "server=123;
    user = 123; database = 123; port = 123; password = 123;
    "); //данные для входа в бд

    MySqlConnection con = new MySqlConnection(); //создание переменной для удобства
    int used = 0; MySqlCommand cmnd = con.CreateCommand(); //команда для бд
    var a = cmnd.ExecuteReader(); //чтение из бд
    string HWIDlocal = System.Security.Principal.WindowsIdentity.GetCurrent().User.Value; //получаем хвид компа
    string HWID = $ "UPDATE LoginedChuvaku SET HWID = {HWIDlocal} WHERE ID = '{a.GetString("
    UID ")}'"; //изменение значения в бд
    string useeed = $ "UPDATE LoginedChuvaku SET used = {used} WHERE ID = {a.GetString("
    UID ")}"; //изменение значения used в бд
    con.ConnectionString = database.ConnectionString; //подключение к бд
    con.Open(); //открыть бд
    MySqlCommand hwid = new MySqlCommand(HWID, con); //команда для изменения хвида
    MySqlCommand useed = new MySqlCommand(useeed, con); //команда для изменения значения used в бд

    while (a.Read()) {
      if (a.GetInt32("used") == used) {
        hwid.ExecuteNonQuery();
        useed.ExecuteNonQuery();
        Clipboard.SetText(HWID);
        //дебаг      MessageBox.Show($"HWID установлен {HWID} {HWIDlocal} {a.GetString("UID")} {used}");
        con.Close();
      } else {
        MessageBox.Show("HWID уже установлен.");
        con.Close();
      }
    }

Обновленный код, с которым все работает:

private protected bool PseudoProverka(string login, string pass) {
    try {
        var database = new MySqlConnectionStringBuilder(@ "server=123;
        user = 123; database = 123; port = 123; password = 123;
        ");

        MySqlConnection con = new MySqlConnection(); //создание переменной для удобства
        int used = 0; int used1 = 1; con.ConnectionString = database.ConnectionString; //подключение к бд
        con.Open(); //открытие бд
        MySqlCommand cmnd = con.CreateCommand(); //команда для бд
        cmnd.CommandText = $ "SELECT * FROM LoginedChuvaku WHERE Login = '{login}'"; //получаю информацию из бд по логину
        var a = cmnd.ExecuteReader(); //чтение из бд
        string HWIDlocal = System.Security.Principal.WindowsIdentity.GetCurrent().User.Value; //получаем хвид компа

        while (a.Read()) {
            if (a.GetInt32("used") == used) {
            string HWID = $ "UPDATE `LoginedChuvaku` SET `HID` = '{HWIDlocal}' WHERE `LoginedChuvaku`.`UID` = {a.GetString("
            UID ")}"; //изменение значения в бд
            string useeed = $ "UPDATE `LoginedChuvaku` SET `used` = '{used1}' WHERE `LoginedChuvaku`.`UID` = {a.GetString("
            UID ")}"; //изменение значения used в бд 
            MySqlCommand hwid = new MySqlCommand(HWID, con); //команда для изменения хвида в бд
            MySqlCommand useed = new MySqlCommand(useeed, con); //команда для изменения значения used в бд
            a.Close();
            hwid.ExecuteNonQuery();
            useed.ExecuteNonQuery();
            } else {
            MessageBox.Show("HWID уже установлен.");
            }
        }
        }
        catch (Exception e) {
        MessageBox.Show(e.Message);
        }
        return false;
    }

Ответы (1 шт):

Автор решения: Alexander Petrov

Насколько я могу судить, ваш код обновляет колонки HID и used у найденной записи с логином и значением used равным нулю.

Это можно сделать одним запросом UPDATE. Не нужно делать предварительный SELECT.

string sql = @"UPDATE `LoginedChuvaku`
               SET `HID` = @hid, `used` = 1
               WHERE `Login` = @login AND `used` = 0";

string hwid = WindowsIdentity.GetCurrent().User.Value;

using (MySqlConnection con = new MySqlConnection(_connectionString))
{
    con.Open();

    using (MySqlCommand cmnd = con.CreateCommand())
    {
        cmnd.CommandText = sql;
        cmnd.Parameters.Add("hid", MySqlDbType.VarChar).Value = hwid;
        cmnd.Parameters.Add("login", MySqlDbType.VarChar).Value = login;

        int rowsAffected = cmnd.ExecuteNonQuery();
    }
}

Постараюсь объяснить, что тут к чему.

Не нужно создавать MySqlConnectionStringBuilder при каждом вызове метода. Строку соединения следует получить в конструкторе класса и сохранить в поле. Далее просто используем это поле _connectionString.

Ресурсы нужно обязательно освобождать. Для этого MySqlConnection и MySqlCommand обёрнуты в using. Пока просто скопируйте, со временем поймёте, почему это необходимо.

Значения переменных used и used1 фактически являются константами, т. к. никогда не меняются, поэтому я просто перенёс их в sql-запрос.

А вот значения для Login и HID следует задавать параметрами. Это обезопасит от sql-инъекций и в целом ускорит выполнение множества запросов.
Я указал тип параметров MySqlDbType.VarChar - замените его на тот, который указан в таблице БД (я не могу знать точный тип).

Метод ExecuteNonQuery возвращает количество задействованных строк. Можете добавить в код проверку, что-то вроде:

if (rowsAffected >= 1)
{
    // обновление произошло
}
else
{
    // обновление не произошло
}

Вставьте в ветки if нужную реакцию.


Ваш метод принимает параметр string pass, но никак его не использует. Вероятно, его следует или удалить, или использовать в запросе в WHERE.

Ваш метод возвращает параметр bool. Но никогда не возвращает true. Вероятно, метод следует сделать void.

Старайтесь давать говорящие имена переменным. used1, useed - плохие название.
Также мне не очень понятны аббревиатуры hid, hwid. Имхо, там должен быть sid - security identifier.

Имена LoginedChuvaku и PseudoProverka тоже надо бы заменить.

→ Ссылка