0

Two forms and separate class(DataConn) for data access in my project. Button from Form1 opens Form2 and this(child) form calls GetData method from DataConn class to populate Form2 textbox with a name. Form2 has button for retrieving next record which is calling the NavigateRecords method in DataConn class. The NavigateRecord method is called from inside GetData in order to populate the textbox in Form2, when it loads, but also for retrieving next record from Form2’s Next event. When NavigateRecords is called from Form2 Next button event the error ‘Object reference not set to an instance of an object’ on this line: myDR = myDS.Tables["People"].Rows[increment]; in NavigateRecords. Why does this not happen when the same line executes upon Form2 load event? If I create an instance of the DataRow the warning 'System.Data.DataRow(System.Data.DataRowBuilder) is inaccessible due to its protection level.

DataConn class:

public class DataConn
{
    private DataSet myDS;
    private DataRow myDR;
    private int maxRows = 0;
    private int increment = 0;
    private string name;

    public int MaxRows
    { get { return maxRows; } }

    public int Increment
    { get { return increment; } set { increment = value; } }

    public string Name
    { get { return name; } }

    public void GetData()
    {
        // class variable
        string connectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Temp\Testing\TestDatabase.accdb";

        //everything created in 'using' gets destroyed/goes out of scope at end of 'using' block.
        using (OleDbConnection myConn = new OleDbConnection(connectionString))
        {
            string SQL = "SELECT * From Test";
            OleDbDataAdapter myDA = new OleDbDataAdapter(SQL, myConn);
            myDS = new DataSet();
            try
            {
                myConn.Open();
                myDA.Fill(myDS, "People");
                NavigateRecords();  //called to populate textbox in NewForm
                maxRows = myDS.Tables["People"].Rows.Count;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                myConn.Close();
            }
        }
    }

    public void NavigateRecords()
    {
        try
        {
            myDR = myDS.Tables["People"].Rows[increment];//exception             
            name = myDR.ItemArray.GetValue(1).ToString();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
        finally
        {
        } 

    }
}

Form2 Load and Next_CLick events:

private void frmNewForm_Load(object sender, EventArgs e)
    {
        DataConn theConn = new DataConn();
        theConn.GetData();
        txtName.Text = theConn.Name;
    }

private void btnNext_Click(object sender, EventArgs e)
    {
        DataConn theConn = new DataConn();
        if (theConn.Increment != theConn.MaxRows - 1)
        {
            theConn.Increment++;
            theConn.NavigateRecords();
            FillTextBox();
        }

EDIT: I created a new project and included everything within the form class itself. Datarow is initially null and when called in NavigateRecords method is set to System.Data.DataRow and remains so as long as form is open. In my original project when the the datarow is called again from Form2’s next event it is back to null and exception is thrown. Why does it matter that it is null when it was null to start with?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
KFP
  • 699
  • 3
  • 12
  • 33
  • Almost all cases of `NullReferenceException` are the same. Please see "[What is a NullReferenceException in .NET?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net)" for some hints. – John Saunders Jun 20 '13 at 17:34

1 Answers1

0

Try this:

DataConn theConn;
private void frmNewForm_Load(object sender, EventArgs e)
{
    theConn = new DataConn();
    theConn.GetData();
    txtName.Text = theConn.Name;
}

private void btnNext_Click(object sender, EventArgs e)
{
    if (theConn.Increment != theConn.MaxRows - 1)
    {
        theConn.Increment++;
        theConn.NavigateRecords();
        FillTextBox();
    }
}
King King
  • 61,710
  • 16
  • 105
  • 130
  • the first time Next is selected it doesn't cause the error, but the second time does. the datarow and dataset are null at that point. – KFP Jun 20 '13 at 18:03
  • I also had theConn = new DataConn(); in the FillTextBox method and once I removed that it no longer envoked the error. Am I understanding this correctly that since I was creating a new instance of a new DataConn in form load, btnNext and FillTextBox that it then refered to a new instance each time and so datarow and dataset where then set at null for new instances?? I'm glad it works now, but I still want to understand what was going on. thanks! – KFP Jun 20 '13 at 18:18
  • @KFP your `theConn` created in the `btnNext_Click` is a new instance without calling `GetData()` and that's why the table `People` doesn't exist (not loaded), I don't think you want to `GetData()` each time the Next button is clicked, so the solution is to use a local variable for your `theConn` and use it in different methods in the class. – King King Jun 20 '13 at 18:29
  • I would I use a local variable for my class instance? – KFP Jun 20 '13 at 18:59
  • I meant 'How would I'? It is still goign to refer to DataConn and call GetData each time. – KFP Jun 20 '13 at 19:10
  • @KFP I think you have to call `GetData()` only 1 time in the `Form_Load`, all other operations are applied on the loaded data, I see that there is only 1 `GetData()` in your `Form_Load`, if you have any other `GetData()` in your code (which is called from the `theConn`), you should consider it if it's really what you want. That depends on your design, normally I have an object holding all the data and loads data only 1 time, all other data manipulations such as editing, deleting, adding and navigating are applied on the `existing loaded data` not on `any new instance` as you did in your code. – King King Jun 20 '13 at 19:23