Mahmoud
Mahmoud

Reputation: 197

The ConnectionString property has not been initialized. Appears when refreshing the gridView

I am trying to fill a dataGridView with a data from database, it must get the data when the form is loaded & and when a refreshButton clicked..

here's the code:

public partial class PhoneBookMainWindow : Form
{
    static public string connString = "Server=(local); Database=PhoneBook; Trusted_Connection=TRUE";
    public SqlConnection connection = new SqlConnection(connString);
    private void btnRefreshPhoneBook_Click(object sender, EventArgs e)
    {
        SqlCommand command = new SqlCommand("SELECT ID, contactName, jobTitle, currentAddress, workAddress, workPhone, cellPhone FROM ContactsInformations", connection);
        try
        {
            SqlDataAdapter dataAdapter = new SqlDataAdapter();
            dataAdapter.SelectCommand = command;
            DataTable dataSet = new DataTable();
            dataAdapter.Fill(dataSet);
            BindingSource bindingSrc = new BindingSource();

            bindingSrc.DataSource = dataSet;
            dataGridView1.DataSource = bindingSrc;
            dataAdapter.Update(dataSet);
        }
        catch (Exception x)
        {
            MessageBox.Show(x.Message);
            throw;
        }

    }
}

Am using the same code in Form loading & btn clicking and they work rightly in the execution, but the problem is appear when i delete a row from database ( using a query by click a delete btn then click the refresh btn the exhibition come to my face.

Upvotes: 2

Views: 2922

Answers (1)

David
David

Reputation: 219027

The issue you seem to be facing is that you have multiple code blocks sharing the same SqlConnection object. Potential race conditions aside, this means that any one of them may try to dispose of that object before another one has used it.

Once disposed, the object is no longer in a state where you can use it. Specifically in this case, it doesn't have a .ConnectionString set anymore.

Essentially, this is happening:

  • Class A initializes the connection
  • Method A1 uses the connection
  • Method A1 finishes the connection and disposes of it
  • Method A2 tries to use the connection, but can't because it's disposed

Creating a SqlConnection object isn't a particularly resource-intensive process, so it's best to scope it locally to the code that's going to use it. Something like this:

using (SqlConnection connection = new SqlConnection(connString))
{
    using (SqlCommand command = new SqlCommand("SELECT ID, contactName, jobTitle, currentAddress, workAddress, workPhone, cellPhone FROM ContactsInformations", connection))
    {
        try
        {
            SqlDataAdapter dataAdapter = new SqlDataAdapter();
            dataAdapter.SelectCommand = command;
            DataTable dataSet = new DataTable();
            dataAdapter.Fill(dataSet);
            BindingSource bindingSrc = new BindingSource();

            bindingSrc.DataSource = dataSet;
            dataGridView1.DataSource = bindingSrc;
            dataAdapter.Update(dataSet);
        }
        catch (Exception x)
        {
            MessageBox.Show(x.Message);
            throw;
        }
    }
}

I've done two things here:

  1. The SqlConnection object is created inside the method, instead of at the class level. Which means nothing except this method will use it. (So nothing except this method can break it.)
  2. I've wrapped some disposable objects in using statements, which is best practice when working with anything that implements IDisposable.

Upvotes: 6

Related Questions