0

I'm trying to track down a .NET error in my little game here.

Here is the error:

ArgumentNullException: 'table' argument cannot be null

System.DataSet.Merge(DattaTable table)

It's occurring on the line below where it tries to merge a table into an existing dataset.

I'm trying to do as many checks as I think I can to determine if the dataset or table are empty, but it continues to error on the ds.Merge line.

Dim ds As DataSet
'getData = simple function that uses SqlConnection & SqlDataAdapter to get data from my database
ds = utils.getData("Sproc_GetGameEncounters")

Dim MonsterDataSet As DataSet

MonsterDataSet = utils.getData("Sproc_MonsterDataSetFromDB")

If Not MonsterDataSet Is Nothing Then
    If MonsterDataSet.Tables("TreasureList") Is Nothing OrElse MonsterDataSet.Tables("TreasureList").Rows.Count = 0 Then
        'MonsterDataSet.Tables("TreasureList") is  empty
    Else
        ds.Merge(MonsterDataSet.Tables("TreasureList"))  'line where error occurs
    End If
End If

Are there more checks I could add to help fix or at least track down this error?

Thanks!

SkyeBoniwell
  • 6,345
  • 12
  • 81
  • 185
  • 1
    Use debugger to ensure a table exists named TreasureList in MonsterDataSet. – NoAlias Mar 07 '18 at 18:19
  • 1
    `Dim MonsterDataSet As DataSet` does not create a DataSet, it simply declares an object variable. Unless `utils.getData` returns a DataSet (not DataTable) it will be Nothing. That seems like it would result in an NRE though. So whatever that mysterious helper does, it does not create a table by that name in that dataset...at least not always. That code doesnt show any of those things being created – Ňɏssa Pøngjǣrdenlarp Mar 07 '18 at 18:21
  • 1
    Seems like that "helper" method is less helpful (or less smart) than it could be. If it returned a DataTable, rather than 2 DataSets, you could simply add each table to a single dataset when you call it. – Ňɏssa Pøngjǣrdenlarp Mar 07 '18 at 18:28
  • 1
    Is there multithreading involved? – JustAPup Mar 07 '18 at 18:38
  • Hi @Minh, how would I determine that? There are multiple players for this game... – SkyeBoniwell Mar 07 '18 at 18:41
  • 1
    The problem seems to be that MonsterDataSet.Tables("TreasureList") has some value at one instance and null the next. This can happen because of race conditions. Can the players modify the TreasureList? – JustAPup Mar 07 '18 at 18:46
  • @Minh yes they can... – SkyeBoniwell Mar 07 '18 at 18:56
  • 2
    More than likely. the table created is not named. Since the "helper" isnt told the TableName, it most likely doesnt have one. Ergo `dsMosnter.Tables("anything")` will return null. It only takes 3 lines of code to create a DataTable in a DataSet, so it is not clear why `getData` exists. – Ňɏssa Pøngjǣrdenlarp Mar 07 '18 at 19:27

1 Answers1

0

I had the same problem recently. The problem is the adapter, it not get the names of tables. I have a similar function and I'm happy to share it.

You can set the table name after dataset filled, or with TableMappings (here an answer for TableMappings), but I preferred the first way.

Function to fill the dataset

    Private Function sql_fillDataset(sql As String, Optional tablesName As String() = Nothing) As DataSet


        dim sql_connection As SqlConnection
        Dim command As SqlCommand
        Dim adapter As New SqlDataAdapter
        Dim ds = New DataSet

        Try

            sql_connection = New SqlConnection("YOUR_CONNECTION_STRING")
            sql_connection.Open()

            command = New SqlCommand(sql, sql_connection)

            adapter.SelectCommand = command
            adapter.Fill(ds)

            If Not tablesName Is Nothing AndAlso Not ds Is Nothing AndAlso Not ds.Tables Is Nothing AndAlso ds.Tables.Count = tablesName.Length Then
                For i = 0 To ds.Tables.Count - 1
                    ds.Tables(i).TableName = tablesName(i)
                Next
            End If

            command.Dispose()
            adapter.Dispose()
            sql_connection.Close()
            sql_connection.Dispose()

            Return ds
        Catch ex As Exception
            Return Nothing
        End Try

    End Function

How to use it

Dim ds As New Dataset
ds = sql_fillDataset("SELECT * FROM TABLE1")
' #### Here is your case, and you haven't the table name
ds.tables(0)

Or

Dim ds As New Dataset
ds = sql_fillDataset("SELECT * FROM TABLE1", New String() {"TABLE1"})
' #### Here is your solution, but the dataset have the name !!
ds.tables("TABLE1")

Or with more than one tables

Dim ds As New Dataset
ds = sql_fillDataset("SELECT * FROM TABLE1; SELECT * FROM TABLE2", New String() {"TABLE1", "TABLE2"})
ds.tables("TABLE1")
ds.tables("TABLE2")

Hope this help you.

Baro
  • 5,300
  • 2
  • 17
  • 39