Link to home
Start Free TrialLog in
Avatar of sirbounty
sirbountyFlag for United States of America

asked on

Object reference not set to an instance of an object.

Getting this error in my project.  https://filedb.experts-exchange.com/incoming/ee-stuff/90-ch3.zip

An unhandled exception of type 'System.NullReferenceException' occurred in WindowsApplication2.exe

Additional information: Object reference not set to an instance of an object.
Avatar of razorback041
razorback041
Flag of United States of America image

debug it, and paste the code that it fails on...some additional code(before and after) would be helpful...maybe the whole function
Avatar of sirbounty

ASKER

Form code....

    Private Sub frmList_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Fill the dataset for the list box
        daLastName.Fill(DsLastName1)
        'Set the combo box for no current selection
        cboLastName.SelectedIndex = -1
    End Sub

    Private Sub cboLastName_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboLastName.SelectedIndexChanged
        'Get the record to match the selection
        If cboLastName.SelectedIndex <> -1 Then
            DsEmployee1.Clear()
            daEmployee.SelectCommand.Parameters("@lname").Value = cboLastName.Text  <----Fails here with the error mentioned above
            daEmployee.Fill(DsEmployee1)
        End If
    End Sub
End Class
Avatar of Sancler
Sancler

When a combobox is bound to a datasource its .SelectedIndexChanged event appears to fire either when the binding is declared, if the datasource is already filled with data, or when the datasource is filled with data, if the binding is done first.  And, when that happens, it seems that the .SelectedIndex property for which it fires will not always be -1.

So my guess on this one is that your code is firing during you form load as part of that process and that, when it does fire, the cboLastName.Text is a null value.  Try declaring

   Dim Loading As Boolean = True

at the start of your form, putting

   If Loading Then Exit Sub

as the first line of your cboLastName_SelectedIndexChanged sub, and only putting

   Loading = False

at some point in your code when all the binding and dataloading that afects the combobox has been done.

Roger

 
The form loads fine - no errors.
It's only when I select a Last Name from the combo that it generates this error.

I did try that anyway and still get the same error.

try changing cboLastName.Text to cboLastNames.selectedvalue
same error
1) If you select 'daEmployee', you will notice that the SelectCommand property is nothing, so you can't execute this line:

daEmployee.SelectCommand.Parameters("@lname").Value = cboLastName.Text

2) Is this a lesson out of a book?

3) Why use ODBC?  Why not OleDb?

Bob

Yes, it's a practice lesson (Lord knows I could use all I can get in that area).
The book actually points to using an sql adapter.  I've had some difficulty working that angle.  I'm sure it's a pilot error, so I went (aimlessly) where I could.

I'll check that out - thanx Bob! :^)
I get that stupid "No mapping exists" error...(https://www.experts-exchange.com/questions/21843485/No-mapping-exists-from-DbType-SByte-to-a-known-OdbcType.html).  
I have to fiddle with it to get it working...
Still does the same thing Bob (and I 'thought' that my sql was in there before).
I did generate a new ds as well (overwriting original).
<sigh>
i think you are getting the error in this line
DsEmployee1.Clear()

try changing it to, i think initially DsEmployee1 is not filled.

            If Not IsNothing(DsEmployee1) Then
                DsEmployee1.Clear()
            End If
On the project as you originally posted it, these are the totality of references to da.Employee

*********

In the Windows Generated Region

  in Declarations

    Friend WithEvents daEmployee As System.Data.Odbc.OdbcDataAdapter

  in InitializeComponent sub

        Me.daEmployee = New System.Data.Odbc.OdbcDataAdapter

        '[...]

        'daEmployee
        '
        Me.daEmployee.TableMappings.AddRange(New System.Data.Common.DataTableMapping() {New System.Data.Common.DataTableMapping("Table", "employee", New System.Data.Common.DataColumnMapping() {New System.Data.Common.DataColumnMapping("lname", "lname")})})

And in the cboLastName_SelectedIndexChanged sub

            daEmployee.SelectCommand.Parameters("@lname").Value = cboLastName.Text
            daEmployee.Fill(DsEmployee1)

********

So, as Bob says, when it reached the lines in the cboLastName_SelectedIndexChanged sub, there wasn't a SelectCommand for the daEmployee and, as there was no such command, there couldn't be any parameters for it either.

It looks, from your later postings, as though you've tried to correct that - "I 'thought' that my sql was in there before" - but how did you do that?  What code did you use, and where did you put it?  It looks as though the original code was generated by dragging data components onto the form.  If that is so, the easiest approach might be to delete the existing daEmployee, drag a new one on to the form and re-configure it.  That should not only make sure that the select command and parameters are there but also that the table mappings are re-done.

Roger

PS  I doubt that there would be a problem with DsEmployee1.Clear().  DsEmployee1 seems to have been properly declared.  As (I agree) it would not have been filled, the .Clear() would not actually do anything, but I don't think it would throw an error.
Correct - the Clear() does not generate the error.
This is a textboox hands-on that initially began with a simple drop down of the last names.  At that time, my select statement was simply 'select lname from employee'.
The other problem I have is - when I 'do' drag the table (from server explorer), it always generates an error, so I end up adding the components manually.
I've started from scratch twice on this thing and run into the same issues each time.  
How did I correct it?  I right clicked on daEmployee, and modified the sql from the 'wizard' there.  Even now looking at it, it is set to "select .... from ... where lname='@lname'"

So, this time I went to the odbccommand1, renamed it to cmdEmployee, added the active con (conPubs) and then modified the commandtext to the same select statement.

This time, when I run it - I get this error:

An unhandled exception of type 'System.IndexOutOfRangeException' occurred in system.data.dll

Additional information: An OdbcParameter with ParameterName '@lname' is not contained by this OdbcParameterCollection.

>>"select .... from ... where lname='@lname'"
 try removing the single quotes around @lname
invalid property value
>>
this time I went to the odbccommand1, renamed it to cmdEmployee, added the active con (conPubs) and then modified the commandtext to the same select statement
<<

>>
Additional information: An OdbcParameter with ParameterName '@lname' is not contained by this OdbcParameterCollection.
<<

And did you also modify the list of parameters for odbccommand1 so that they became parameters for cmdEmployee?

How about doing what I did a few posts up and going through the code extracting all the references to the relevant dataadapter and posting that?

Roger
>>did you also modify the list of parameters for odbccommand1 so that they became parameters for cmdEmployee<<

I actually renamed odbccommand1 to cmdEmployee.
   Friend WithEvents daLastName As System.Data.Odbc.OdbcDataAdapter
    Friend WithEvents DsLastName1 As WindowsApplication2.dsLastName
    Friend WithEvents dvLastName As System.Data.DataView
   
    Friend WithEvents daEmployee As System.Data.Odbc.OdbcDataAdapter
    Friend WithEvents DsEmployee1 As WindowsApplication2.dsEmployee
   
    Friend WithEvents cmdEmployee As System.Data.Odbc.OdbcCommand

   
    Me.cmdSQLLName = New System.Data.Odbc.OdbcCommand
    Me.daLastName = New System.Data.Odbc.OdbcDataAdapter
    Me.DsLastName1 = New WindowsApplication2.dsLastName
    Me.dvLastName = New System.Data.DataView
    Me.daEmployee = New System.Data.Odbc.OdbcDataAdapter
    Me.DsEmployee1 = New WindowsApplication2.dsEmployee
    Me.cmdEmployee = New System.Data.Odbc.OdbcCommand
    CType(Me.DsLastName1, System.ComponentModel.ISupportInitialize).BeginInit()
    CType(Me.dvLastName, System.ComponentModel.ISupportInitialize).BeginInit()
    CType(Me.DsEmployee1, System.ComponentModel.ISupportInitialize).BeginInit()
   
    Me.cmdSQLLName.CommandText = "SELECT lname FROM employee"
    Me.cmdSQLLName.Connection = Me.conPubs
   
    Me.daLastName.SelectCommand = Me.cmdSQLLName
    Me.daLastName.TableMappings.AddRange(New System.Data.Common.DataTableMapping() {New System.Data.Common.DataTableMapping("Table", "employee", New System.Data.Common.DataColumnMapping() {New System.Data.Common.DataColumnMapping("lname", "lname")})})
   
    Me.DsLastName1.DataSetName = "dsLastName"
    Me.DsLastName1.Locale = New System.Globalization.CultureInfo("en-US")
   
    Me.dvLastName.Sort = "lname"
    Me.dvLastName.Table = Me.DsLastName1.employee
 
    Me.daEmployee.SelectCommand = Me.cmdEmployee
    Me.daEmployee.TableMappings.AddRange(New System.Data.Common.DataTableMapping() {New System.Data.Common.DataTableMapping("Table", "employee", New System.Data.Common.DataColumnMapping() {New System.Data.Common.DataColumnMapping("lname", "lname")})})
   
    Me.DsEmployee1.DataSetName = "dsEmployee"
    Me.DsEmployee1.Locale = New System.Globalization.CultureInfo("en-US")
   
    Me.cmdEmployee.CommandText = "SELECT emp_id, fname, lname, hire_date FROM employee WHERE (lname = @lname)"
    Me.cmdEmployee.Connection = Me.conPubs
Originally the code would have loooked something like

   Me.odbccommand1.CommandText = <Whatever>
   Me.odbccommand1.Connection = <whatever>
   Me.odbccommand1.Parameters.Add(<whatever>)

What was asking was whether, when you did the renaming, you renamed ALL parts including

   Me.odbccommand1.Parameters.Add(<whatever>)

The code you've now posted shows that you didn't.  Or, if you did, it's gone missing somewhere.

Roger
I've got

 Me.cmdEmployee.CommandText = "SELECT emp_id, fname, lname, hire_date FROM employee WHERE (lname=@lname)"
        Me.cmdEmployee.Connection = Me.conPubs

But, I don't add the parameters until the selectedindexchange of the combo box...
No, you don't add the parameter then.  What you add in "the selectedindexchange of the combo box" is the VALUE that you want the named parameter to have.  The Parameter, on the one hand, and the Parameter's Value, on the other hand, are different.  Until a parameter has been added to the Parameters Collection of cmdEmployee there is no parameter for a parameter's value to be given to.

In your command text

 Me.cmdEmployee.CommandText = "SELECT emp_id, fname, lname, hire_date FROM employee WHERE (lname=@lname)"

you are indicating, with the bit that says "(lname=@lname)", that when the select command is run it should look for the value to which lname should be equal in a parameter called @lname.  But that is not enough to create that parameter.  That has to be done with something like

  Me.cmdEmployee.Parameters.Add("@lname", OdbcType.VarChar)

The first argument is the parameter's name, the second is its datatype.  I say "something like ..." as I'm not used to working with ODBC.  Try putting that immediately after

       Me.cmdEmployee.Connection = Me.conPubs

and see if it works.  If it doesn't, then have a look in the help files for OdbcParameter Constructor and try other versions.  What I was hoping was that the wizard would originally have created the parameter with code equivalent to the above, but perhaps - because of the difficulties you say you've had with the wizard - it didn't.

Keep at it.  You're nearly there ;-)

Roger
Thanx for the encouragement.  I'm a long way from my ultimate goal though (understanding all this!).

I found this site: http://www.codeproject.com/cs/database/odbcnet_syb_stp.asp which, I think, shows how to use the Parameters, but I'm not sure how OdbcType should be declared?
How about using the code in this link as your pattern?

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdataodbcodbcdataadapterclassselectcommandtopic.asp

The first few lines are doing something very similar to what you want to do: that is, have a select statement with a where clause in it.  And its in VB.NET, which the code in the link you posted isn't - though it's easily translatable.  The major difference is that the example uses two parameters, rather than one.  But it illustrates the approach and would need very little modification.

As I said, I'm not used to working with ODBC, but it looks like this

    Me.cmdEmployee.CommandText = "SELECT emp_id, fname, lname, hire_date FROM employee WHERE (lname = ?)"
    Me.cmdEmployee.Connection = Me.conPubs
    Me.cmdEmployee.Parameters.Add("@lname", OdbcType.VarChar, 50)

should do it for you.  I've guessed at the size of the lname field.  If it's different from 50, you can substitute some other number.  You will notice that I've changed the (lname = @lname) to (lname = ?).  That's because that's how the example does it.  So it looks like ODBC is like OleDb (and different from SQL) and marks its parameters with "?" rather than a name beginning with "@".

Roger
Man, ya gotta love Roger (aka THE ADO.NET guy)!!!

I was sitting at work reading these comments without the ability to respond.   Luckily, somebody else could pick up the ball.

Bob
Yay!  I got a bit further...

Now it errors/halts at the "End If" with the following:

An unhandled exception of type 'System.InvalidCastException' occurred in system.data.dll
Additional information: Object must implement IConvertible.

Of the cbo, my Index=7, text is "", and Value (which is what it's set to use) returns:
{System.Data.DataRowView}
    [System.Data.DataRowView]: {System.Data.DataRowView}

<sigh>
Should I give up and move on to the next section?  I think I know how it's "supposed" to work...very frustrating when the 'book' doesn't show the correct way to accomplish these tasks...I copied it almost precisely... : (
Would it be relatively easy to switch gears to oledb?
>>
I copied it almost precisely
<<

I don't know whether the 'book' is wrong or it's that word 'almost' ;-)

The problem now seems to be that the last names data is not getting to the combobox.  The combobox is bound to a dataview

        Me.cboLastName.DataSource = Me.dvLastName

That dataview's table is declared by this line

        Me.dvLastName.Table = Me.DsLastName1.employee

But when the data for last name is brought over from the database it is done with this line

        daLastName.Fill(DsLastName1)

That means that it is just dumped in a datatable in the dataset having the default name of "Table", rather than being put in a datatable named "employee" which is what the dataview is relying on.

My guess is that there was (there certainly should have been) in the original code a line giving a table mapping to the daLastName dataadapter.  But I gather from a comment above (although the other thread to which it refers has now been deleted) that you've had problems with table mappings.  So rather than reinstating (or re-coding that) you should be able to overcome the problem by changing this line

        daLastName.Fill(DsLastName1)

to this

        daLastName.Fill(DsLastName1, "employee")

That will make sure that the data goes in a datatable with the name that the dataview expects.  Another alternative would be to change this line

        Me.cboLastName.DataSource = Me.dvLastName

to

        Me.cboLastName.DataSource = Me.DsLastName1.Tables(0)

which would bind the combobox direct to the (first and only) table in DsLastName1 and get the last name data already sorted (rather than relying on the dataview to do the sorting) by changing the SelectCommand CommandText from

       "SELECT lname FROM employee"

to

       "SELECT lname FROM employee ORDER BY lname"

Re a switch to oledb.  Provided you have a database - usually .mdb - to work with with oledb, yes, a switch would be easy.  In principle, I'm not sure that it would make it any easier to learn.  The basics are very similar, it's just some of the detailed syntax that differs, and oledb has its own quirks.  But you might find that the wizards work better with it.

Roger
I sincerely appreciate the effort and time you've put forth explaining all this to me.

By 'almost', I meant only that the book example was with using an sql da.  I was unable to do this (for reasons I'll exclude here, but probably are worth the effort of another question, since this seems to be the books standard adapter).

So, I couldn't be certain that everything would be the same.  I suppose I grabbed the odbc, not really thinking about it, and had typically used ole myself (oops).


>>The problem now seems to be that the last names data is not getting to the combobox.<<

But, it is there...  When I run the program, the combo is populated.  The errors start occuring when I actually choose a Last name from the cbo.
The purpose of this exercise was supposed to show how you're better off binding to a dataview, cause you (supposedly) can't sort it otherwise (?).

The text reads:  When you want to display the data in alphabetical order...you can usually set Sorted to True.  Unfortunately, this does not work when bound to a data source.

But it would also make sense to simply order it via the sql statement.

>> But I gather from a comment above ... that you've had problems with table mappings.<<
Yes, and if you have any suggestions on 'that' problem, I'd be more than glad to reopen it!

So, I tried it again with the change you suggested above (adding "employee" as the table name).  It's still halting at the same spot, but I just identified the 'spot' as the line above the End If (the End If gets highlighted in green, thus my confusion).  So, it's actually this line causing the problem :

daEmployee.Fill(DsEmployee1)

Thanx again for your patience and time! I really appreciate it.
ASKER CERTIFIED SOLUTION
Avatar of Sancler
Sancler

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
No apology necessary.
Whoo hoo...it's finally working! :)
Thank you, thank you, thank you!

Now, on to the next project...I hope you'll be around for a while...haha. :^)
Glad it's sorted.  And - despite the serial frustrations of it not working - I think you'll find that it did throw up a few useful learning points.  And that, after all, is what the exercise was really about.

Thanks for the points.

Roger