ExecuteScalar требует открытого и доступного соединения.Текущее состояние соединения закрыто - PullRequest
0 голосов
/ 20 апреля 2019

При попытке зарегистрировать новую учетную запись в моей программе через LocalDB я получаю сообщение об ошибке:

ExecuteNonQuery требует открытого и доступного соединения. Текущее состояние соединения закрыто

Но, как вы видите, я уже открываю соединение

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


// The  methods which will be called if the user tries to log in or register
        private void LoginRegisterClick(object sender, EventArgs e)
        {
            // The following lines of code will execute if the user tries to register
            if (lblView.Text == "Register")
            {
                // If all the textboxes have passed validation, the details from the textboxes are retrieved and stored
                if (ucRegister1.AllFieldsValidated() == true)
                {
                    string[] details = ucRegister1.ReturnRegisterDetails();
                    // (cmdCountUsernames) Checks to see if new username is unique
                    Helper.ConnectionToDB().Open();
                    SqlCommand cmdCU = new SqlCommand(@"SELECT COUNT(*) FROM LoginsTable WHERE Login = '" + details[6] + "'", Helper.ConnectionToDB());
                    try
                    {
                        int count = (int)cmdCU.ExecuteScalar();
                        //int count = Convert.ToInt32(cmdCU.ExecuteScalar());
                        // If the new username is unique, the record is added into MainParentTable
                        if (count == 0)
                        {
                            try
                            {
                                // Order of the details:         
                                // details[(0)Firstname, (1)Surname, (2)DOB, (3)HomeTel, (4)MobileTel, (5)Address, (6)Username, (7)Password, (8)Email]

                                // (cmdCNL) Creates a new record in the LoginsTable
                                SqlCommand cmdCNL = new SqlCommand(@"INSERT INTO LoginsTable (Login, Password) VALUES (@login, @password)", Helper.ConnectionToDB());
                                Helper.ConnectionToDB().Open();
                                cmdCNL.Parameters.AddWithValue("@login", details[6]);
                                cmdCNL.Parameters.AddWithValue("@password", details[7]);
                                cmdCNL.ExecuteNonQuery();

                                // (cmdFindUserID) Finds the UserID of the new acccount which was just created above.
                                SqlCommand cmdFUID = new SqlCommand(@"SELECT * FROM LoginsTable WHERE Login = @login", Helper.ConnectionToDB());
                                cmdFUID.Parameters.AddWithValue("@login", details[6]);
                                var da = new SqlDataAdapter(cmdFUID);
                                var dt = new DataTable();
                                da.Fill(dt);
                                globalVariables.userIDSelected = dt.Rows[0]["UserID"].ToString();

                                // (cmdInsertMainParentTable) Adds to the MainParentTable, a new parent using the UserID from the code above.
                                SqlCommand cmdIMPT = new SqlCommand(@"INSERT INTO MainParentTable (UserID, FirstName, Surname, DOB, Address, HomeTelephone, MobileTelephone, Email) VALUES (@userid, @firstname, @surname, @dob, @address, @hometelephone, @mobiletelephone, @email)", globalVariables.conDB);
                                cmdIMPT.Parameters.AddWithValue("@userid", globalVariables.userIDSelected);
                                cmdIMPT.Parameters.AddWithValue("@firstname", details[0]);
                                cmdIMPT.Parameters.AddWithValue("@surname", details[1]);
                                cmdIMPT.Parameters.AddWithValue("@dob", Convert.ToDateTime(details[2]));
                                cmdIMPT.Parameters.AddWithValue("@address", details[5]);
                                cmdIMPT.Parameters.AddWithValue("@hometelephone", details[3]);
                                cmdIMPT.Parameters.AddWithValue("@mobiletelephone", details[4]);
                                cmdIMPT.Parameters.AddWithValue("@email", details[8]);
                                cmdIMPT.ExecuteNonQuery();
                                Helper.ConnectionToDB().Close();
                            }
                            catch (Exception msg2)
                            {
                                MessageBox.Show("Error Message 2: " + msg2);
                            }
                        }
                    }
                    catch (Exception msg)
                    {
                        MessageBox.Show("Error Message: " + msg);
                        throw;
                    }
                   // Helper.ConnectionToDB().Close();



                    // Populates and brings ucLogIn to the front of the form
                    ucLogIn1.PopulateLogins(details[6], details[7]);
                    lblView.Text = "Log In";
                    lblView.Location = new Point(293, 30);
                    ucLogIn1.BringToFront();                    
                }
                return;      
            }

Количество должно быть установлено на 0 или 1 в зависимости от результата запроса


GlobalVariables.Con просто делает это

public static SqlConnection conDB = Helper.ConnectionToDB();

Мой вспомогательный класс выглядит следующим образом:

public static class Helper
{
    public static SqlConnection ConnectionToDB()
    {
        return new SqlConnection (@"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename = G:\myDatabase.mdf; Integrated Security = True"); }
    } 
}

1 Ответ

1 голос
/ 20 апреля 2019

Проблема вызвана этой строкой (и аналогичными строками в следующих командах)

SqlCommand cmdCU = new SqlCommand(........, Helper.ConnectionToDB());

Могу поспорить, что ваш Helper.ConnectionToDB создает новые экземпляры объекта SqlConnection при каждом его вызове.

Теперь, даже если у вас есть эта строка

  Helper.ConnectionToDB().Open();

Вы открываете экземпляр соединения, но поскольку команда вызывает снова Helper.ConnectionToDB , вы получаете разные экземпляры в каждой команде и используете их, пока они еще закрыты.

Вам нужен совершенно другой подход

.... previous stuff....
if (ucRegister1.AllFieldsValidated() == true)
{
    string[] details = ucRegister1.ReturnRegisterDetails();
    using(SqlConnection cnn = Helper.ConnectionToDB())
    {
        cnn.Open();
        SqlCommand cmdCU = new SqlCommand("......", cnn);

        .... replace all calls to Helper.ConnectionDB with the cnn variable ....

        .....
    }  // <== This close the connection 
}

Оператор using помогает вам здесь контролировать SqlConnection и используемые им ресурсы. SqlConnection - это одноразовый объект, с которым связаны важные неуправляемые ресурсы. Важно освободить эти ресурсы как можно скорее, и оператор using гарантирует, что при выходе кода из блока using SqlConnection будет закрыт и уничтожен, освобождая ресурсы.

...