Windows Forms App: System.NullReferenceException Error - vb.net

Good day,
I have been trying to figure out the source of error in my application. What this function (GetConcentrations()) is to display data from my database onto a DataGridView. The function is called in the PageLoad but works fine but when I call it in another Sub, I get this error.
Could anyone help me? I already tried different ways.
Thanks!
Here is the code:
Private Sub GetConcentrations()
Dim conString As String = ConfigurationManager.ConnectionStrings("dbAsthmaConnectionString").ConnectionString
Me.dataAdapter = New SqlDataAdapter("Select * from tblConcentrations", conString)
'Dim adapter As New SqlDataAdapter("Select * from tblConcentrations", conString)
Dim dataset As New Data.DataSet
Try
Dim commandBuilder As New SqlCommandBuilder(Me.dataAdapter)
Dim table As New DataTable()
table.Locale = System.Globalization.CultureInfo.InvariantCulture
Me.dataAdapter.Fill(table)
'Dim datasetgetconcentrations = New DataSet
Me.dataAdapter.Fill(dataset)
Me.bindingSource1.DataSource = table
DataGridView3.AutoResizeColumns(DataGridViewAutoSizeColumnMode.AllCellsExceptHeader)
DataGridView3.DataSource = dataset.Tables(0)
dataset.Dispose()
Catch ex As Exception
MsgBox("Failed to display the concentration table (GetConcentrations)!", MsgBoxStyle.Information)
End Try
'Dim ConcentrationValue As Double = DataGridView2.Rows.Contains
'TextBoxCurrentConcentration.Text = txtMessage.Text
End Sub

I don't understand why you call the Fill method two times.
Once to fill a DataTable and one again to fill a DataSet. Only the one for the dataset is really needed.
Could you try if this changes something in your problem?
Dim ds as New DataSet
ds.Locale = System.Globalization.CultureInfo.InvariantCulture
Me.dataAdapter.Fill(ds)
DataGridView3.AutoResizeColumns(DataGridViewAutoSizeColumnMode.AllCellsExceptHeader)
DataGridView3.DataSource = ds.Tables(0)
Also, don't dispose your dataset on exiting, you are still using it.
In this case it's better to let the Garbage Collection handle this task.

Related

stubborn error when trying to merge a table into a dataset

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!
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.

How do I create a dataset in VB.NET from this code?

I currently have the following code in my project which populates a DataGridView object with the results of an SQL query.
Sub PerformQuery(ByVal SQLText As String)
Dim DbConnection As New OleDb.OleDbConnection(createConnectionString)
Dim SQLQuery As String = SQLText
Dim Adapter As New OleDb.OleDbDataAdapter(SQLQuery, DbConnection)
Try
Using Table As New DataTable
Adapter.Fill(Table)
Table.Locale = Globalization.CultureInfo.InvariantCulture
DbConnection.Close()
DataGridView1.DataSource = Table
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Elsewhere in my project I can create a DataSet object using the code
Dim ds As New DataSet
And then extract data from it using code like:
MaxRows = ds.Tables("Dataset_Users").Rows.Count
Rather than populating a DataGridView, how can I use the PerformQuery code to create a dataset?
Thank you in advance for your help.
I think you are after the following:
Try
Dim ds As New DataSet
Using Table As New DataTable
Adapter.Fill(Table)
Table.Locale = Globalization.CultureInfo.InvariantCulture
DbConnection.Close()
DataGridView1.DataSource = Table
ds.Table.Add(Table)
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
Or as in your example you was after the Number of rows in the dataset you can do the same with the DataTable, For Example:
Try
Dim MaxRows As Integer
Using Table As New DataTable
Adapter.Fill(Table)
Table.Locale = Globalization.CultureInfo.InvariantCulture
DbConnection.Close()
DataGridView1.DataSource = Table
'' Getting the number of rows in the DataTable
MaxRows = Table.Rows.Count
End Using
Catch ex As Exception
MsgBox(ex.Message)
End Try
Think in a more functional style. Return the table instead of setting to grid. While we're here, let's update the method so you don't have to write queries anymore that leave you wide open to sql injection attacks:
Function PerformQuery(ByVal SQLText As String, ByVal ParamArray Parameters() As OleDbParameter) As DataTable
Dim result As New DataTable()
Using cn As New OleDb.OleDbConnection(createConnectionString), _
cmd As New OleDb.OleDbCommand(SQLText, cn), _
Adapter As New OleDb.OleDbDataAdapter(cmd, cn)
If Parameters IsNot Nothing AndAlso Parameters.Length > 0 Then
cmd.Parameters.AddRange(Parameters)
End If
Adapter.Fill(result)
End Using
Return Result
End Function
Note that I also removed the error handling and locale code. You still need to do that stuff, but when you want to just return a datatable instead of interact directly with the user interface in a method you have effectively moved your code to a lower level of abstraction. When you do that, you probably don't want to deal with the error handling at this lower level any more; instead let the exceptions bubble up where you can handle them closer to the user interface.
Now you call the updated method like this:
Dim sql As String = "SELECT * FROM Customers WHERE CustomerID = ?"
Dim CustID As New OleDb.OleDbParameter("CustomerId", OleDbType.Integer)
CustID.Value = 123456
Try
DataGridView1.DataSource = PerformQuery(sql, CustID)
Catch Ex As Excpetion
MsgBox(Ex.Message)
End Try

hangs on datagridview .fill large amount of data

Hello I am trying to fill a datagridview with items from a datafile. The code stops on the .fill . I tested the query in excel (Microsoft query) it works fine there. I also tested it (in my vb code) by adding a WHERE to only receive on specific entry, this works fine. Any ideas how to get this to work in my application? Code is below thanks for the help!
Dim dataAdapter As New Odbc.OdbcDataAdapter()
Private Sub ChangeSelect()
Dim selectCommand As String = "SELECT CWIPH.CUST_NO, CWIPH.JOB_NO, CWIPH.JOB_NAME, CJCMS.JOB_DESC FROM { OJ CWIPH CWIPH INNER JOIN CJCMS CJCMS ON CWIPH.JOB_NO = CJCMS.JOB_NO }"
accessDB(selectCommand)
End Sub
Private Sub accessDB(ByVal selectCommand As String)
Dim JobConnectionString As String = "Dsn=Jake; provider=System.Data.Odbc"
Dim cn As OdbcConnection = New OdbcConnection(JobConnectionString)
Dim table As New DataTable()
cn.Open()
Dim cmd As New Odbc.OdbcCommand(selectCommand, cn)
Me.dataAdapter = New Odbc.OdbcDataAdapter(cmd)
With dgvWorkOrder
.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.ColumnHeader
.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.ColumnHeader
End With
Dim commandBuilder As New Odbc.OdbcCommandBuilder(Me.dataAdapter)
Me.dataAdapter.Fill(table)
Me.dgvWorkOrder.DataSource = table
cn.Close()
End Sub
This article helped a lot. What's better: DataSet or DataReader?
So I ended up changing my code to use data reader and so far so good.

Loop through action

I am new to visual basic, however I need to loop through rows in a data table and use the values to in a test script, the script is as follows -
Public Function TestMain(ByVal args() As Object) As Object
StartApp(URL)
' HTML Browser '
Browser_HtmlBrowser(Document_HomePage(),DEFAULT_FLAGS).Maximize()
Button_AddNewProfilesubmit().Click()
'here is where the rows would be read and the loop would start'
Text_Ctl00MainContentProfileNa().Click(AtPoint(6, 13))
Browser_HtmlBrowser(Document_Http1921685526UserCon(), DEFAULT_FLAGS).InputChars("dataBase_Row_Value")
Table_HtmlTable_1().Click(AtCell( _
AtRow(AtIndex(0)), _
AtColumn(AtIndex(1))))
'here is where the loop would end after all rows had been read'
Return Nothing
End Function
I have an idea to achieve this, first doing a database connection, then create the loop -
Dim pName As String
Dim datas As DataSet
Dim datar As DataRow
Dim oledat As SqlDataAdapter
oledat = New SqlDataAdapter("SELECT COLUMN FROM DATABASE",ConnectionString)
oledat.Fill(datas)
For Each datar In datas.Tables(0).Rows
pName = datar.Item("PROFILENAME")
Text_Ctl00MainContentProfileNa().Click(AtPoint(6, 13))
Browser_HtmlBrowser(Document_Http1921685526UserCon(), DEFAULT_FLAGS).InputChars(pName)
Table_HtmlTable_1().Click(AtCell( _
AtRow(AtIndex(0)), _
AtColumn(AtIndex(1))))
Next
However this is breaking, even though there are no errors in Visual Studio, there is only the warning that datas is used before it is assigned the values. Where am I going wrong?
I believe you must initialize a new dataset before working with it. Example:
Dim ds As DataSet = New DataSet()
Dim connection As OleDb.OleDbConnection
Dim command As OleDb.OleDbCommand
Dim adapter As New OleDb.OleDbDataAdapter
Dim connString As String = "my Connection string stuff;"
connection = New OleDb.OleDbConnection(connString)
Try
'open the connection
If connection.State = ConnectionState.Open Then
Else
connection.Open()
End If
'fill each data table
command = New OleDb.OleDbCommand(selectOne, connection)
adapter.SelectCommand = command
adapter.Fill(ds, "someTableName")
Catch ex As OleDb.OleDbException
'error, do something
Finally
'close everything down
adapter.Dispose()
If (Not command Is Nothing) Then
command.Dispose()
End If
connection.Close()
End Try
This example uses OLEDB but should be comparable to what you are doing. Once you fill it, you should be able to iterate over the tables. But, first, check to make sure you have a dataset created first:
If (ds IsNot Nothing) Then
'do for statement here
End If
If this does not work, let me know.

VB.NET: Clear DataGridView

I've tried -
DataGridView1.DataSource=Nothing
and
DataGridView1.DataSource=Nothing
DataGridView1.Refresh()
and
DataGridView1.RefreshEdit()
None of them works..
I've written a method that sets the DataSource of the DataGridView when executed. but each time i execute it, it replicates the data with new value and appends it to the previous contents of the DGV.. I wanna clear the content and then add the values.. Is that possible?
If the DataGridView is bound to any datasource, you'll have to set the DataGridView's DataSource property to Nothing.
If the DataGridView is not bound to any data source, this code will do the trick:
DataGridView.Rows.Clear()
For unbound cases note that:
DataGridView.Rows.Clear()
leaves the Columns collection in place.
DataGridView.Columns.Clear()
..will remove all the columns and rows. If you are using the DGV unbound, and on next use the columns change, clearing the Rows may not be adequate. For library code clear all the columns before adding columns.
I'd probably use this...
DataGridView1.Rows.Clear()
to clear out the rows and then rebind.
Follow the easy way like this
assume that ta is a DataTable
ta.clear()
DataGridView1.DataSource = ta
DataGridView1.DataSource = Nothing
Can you not bind the datagridview to an empty collection (instead of null). That do the trick?
To remove the old record in datagridview when you are searching for new result,with button_click event write the following code,
me.DataGridview1.DataSource.clear()
this code will help to remove the old record in datagridview.
I found that setting the datasource to null removes the columns. This is what works for me:
c#:
((DataTable)myDataGrid.DataSource).Rows.Clear();
VB:
Call CType(myDataGrid.DataSource, DataTable).Rows.Clear()
My DataGridView is also bound to a DataSource and myDataGridView.Columns.Clear() worked fine but myDataGridView.Rows.Clear() did NOT. Just an FYI for those who have tried .Rows.
Don't do anything on DataGridView, just clear the data source. I tried clearing myDataset.clear() method, then it worked.
I've got this code working in a windows form,
Public Class Form1
Private dataStuff As List(Of String)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
DataGridView1.DataSource = Nothing
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
dataStuff = New List(Of String)
dataStuff.Add("qwerty")
dataStuff.Add("another")
dataStuff.Add("...and another")
DataGridView1.DataSource = dataStuff
End Sub
End Class
You should remove the table from dataset if the datagrid is bind to some datatable. Your Gridview will be cleared automatically. No other way.
[YourDatasetName].Tables.Clear()
I had the same problem on gridview content clearing. The datasource i used was a datatable having no columns, and i added columns and rows programmatically to datatable. Then bind to datagridview. I tried the code related with gridview like gridView.Rows.Clear(), gridView.DataSource = Nothing
but it didn't work for me. Then try the below code related with datatable before binding it to datagridview each time.
dtStore.Rows.Clear()
dtStore.Columns.Clear()
gridView.DataSource = dtStore
And is working fine, no replication in DataGridView
1) create button named it Clear.Inside insert tfhe following code
datagridviewer.DataSource=nothing
2) In your search button begin your code by the following statement
datagridviewer.DataSource = DataSet.table
Nb:instead of table put the real name of your table
ex: datagridviewer.DataSource = DataSet.client
When feeding info from an SQL query into a datagridview you can clear the datagridview first before reloading it.
Where I have defined dbDataSet as New DataTable I can do a clear.
dbDataSet must be at the start of the form within the Public Class Form
Dim dbDataset AS New DataTable
within the code of you Private Sub, place
dbDataSet.Clear()
You may have a user scenario such that you want to keep the data binding and only temporarily clear the DataGridView. For instance, you have the user click on a facility on a map to show its attributes for editing. He is clicking for the first time, or he has already clicked on one and edited it. When the user clicks the "Select Facility" button, you would like to clear the DataGridView of the data from the previous facility (and not throw an error if it's his first selection). In this scenario, you can achieve the clean DataGridView by adapting the generated code that fills the DataGridView. Suppose the generated code looks like this:
Try
Me.Fh_maintTableAdapter.FillByHydrantNumber(Me.Fh2010DataSet.fh_maint, hydrantNum)
Catch ex As System.Exception
System.Windows.Forms.MessageBox.Show(ex.Message)
End Try
We are filling the DataGridView based on the hydrant number. Copy this code to the point where you want to clear the DataGridView and substitute a value for "hydrantNum" that you know will retrieve no data. The grid will clear. And when the user actually selects a facility (in this case, a hydrant), the binding is in place to fill the DataGridView appropriately.
If the DataGridView is bound to any datasource,
DataGridView1.DataSource = Nothing
DataGridView1.DataBind()
Dim DS As New DataSet
DS.Clear() - DATASET clear works better than DataGridView.Rows.Clear() for me :
Public Sub doQuery(sql As String)
Try
DS.Clear() '<-- here
' - CONNECT -
DBCon.Open()
' Cmd gets SQL Query
Cmd = New OleDbCommand(sql, DBCon)
DA = New OleDbDataAdapter(Cmd)
DA.Fill(DS)
' - DISCONNECT -
DBCon.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
If the GridView (Say the name is gvArchive) is bound to any DataSource, the following will clear it:
gvArchive.DataSource = Nothing
gvArchive.DataBind()
just write this
DataGridView1.DataSource = ""
I had the same problem: I was programmatically binding my GridView1 to one SQL table [dictonary] or another [meny] BUT when I selected the second table from my RadioButtonList1, I was getting an error (System.Web.HttpException: Field or property with the title [the first column's title from the previously selected table] was not found in the selected data source.) i.e. saying that the columns from my first-selected table couldn't be found. All I needed to do was insert:
GridView1.Columns.Clear()
before adding the table columns. Here goes the full code:
Dim connectionString As String = "your-string-details"
Dim connection As New SqlConnection(connectionString)
Then comes your first Sub:
Private Sub BindOrders()
connection.Open()
Dim sqlCommand As String = "SELECT * FROM [dictionary]"
Dim dataAdapter As New SqlDataAdapter(sqlCommand, connection)
Dim dt As New DataTable()
dataAdapter.Fill(dt)
GridView1.Columns.Clear() ' clear columns before adding new ones
If GridView1.Columns.Count <= 0 Then
Dim Field As New BoundField()
Field.DataField = "id"
Field.HeaderText = "id"
GridView1.Columns.Add(Field)
Field = New BoundField()
Field.DataField = "strArHundreds"
Field.HeaderText = "strArHundreds"
GridView1.Columns.Add(Field)
Field = New BoundField()
Field.DataField = "strArTens"
Field.HeaderText = "strArTens"
GridView1.Columns.Add(Field)
Field = New BoundField()
Field.DataField = "strArSingles"
Field.HeaderText = "strArSingles"
GridView1.Columns.Add(Field)
End If
GridView1.DataSource = dt
GridView1.DataBind()
connection.Close()
End Sub
Then comes your second Sub:
Private Sub BindDocuments()
connection.Open()
Dim sqlCommand As String = "SELECT * FROM [meny]"
Dim dataAdapter As New SqlDataAdapter(sqlCommand, connection)
Dim dt As New DataTable()
dataAdapter.Fill(dt)
GridView1.Columns.Clear() ' clear columns before adding new ones
If GridView1.Columns.Count <= 0 Then
Dim Field As New BoundField
Field = New BoundField
Field.DataField = "id"
Field.HeaderText = "id"
GridView1.Columns.Add(Field)
Field = New BoundField
Field.DataField = "nazev"
Field.HeaderText = "nazev"
GridView1.Columns.Add(Field)
End If
GridView1.DataSource = dt
GridView1.DataBind()
connection.Close()
End Sub
Finally comes your RadioButton:
Protected Sub RadioButtonList1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles RadioButtonList1.SelectedIndexChanged
Dim index As Integer
index = RadioButtonList1.SelectedIndex
Select Case index
Case 0
BindOrders()
Exit Select
Case 1
BindDocuments()
Exit Select
End Select
End Sub
For completion, here is the code for the GridView1 and the RadioButtonList1 in the associated aspx.file:
<asp:RadioButtonList ID="RadioButtonList1"
runat="server"
AutoPostBack="True"
OnSelectedIndexChanged="RadioButtonList1_SelectedIndexChanged">
<asp:ListItem>Obraty</asp:ListItem>
<asp:ListItem>Dokumenty</asp:ListItem>
</asp:RadioButtonList>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
</asp:GridView>
This all works well now.
The mistake that you are making is that you seem to be using a dataset object for storing your data. Each time you use the following code to put data into your dataset you add data to the data already in your dataset.
myDataAdapter.Fill(myDataSet)
If you assign the table in your dataset to a DataGridView object in your program by the following code you will get duplicate results because you have not cleared data which is already residing in your dataset and in your dataset table.
myDataGridView.DataSource = myDataSet.Tables(0)
To avoid replicating the data you have to call clear method on your dataset object.
myDataSet.clear()
An then assign the table in your dataset to your DataGridView object.
The code is like this.
myDataSet.clear()
myDataAdapter.Fill(myDataSet)
myDataGridView.DataSource = myDataSet.Tables(0)
You can try this code:
' clear previous data
DataGridView2.DataSource = Nothing
DataGridView2.DataMember = Nothing
DataGridView2.Refresh()
Try
connection.Open()
adapter1 = New SqlDataAdapter(sql, connection)
' clear data already in the dataset
ds1.Clear()
adapter1.Fill(ds1)
DataGridView2.DataSource = ds1.Tables(0)
connection.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
Use this code where ever you want to implement clear datagridview command
datagridview1.datasource= nothing
datagridview1.datasource= ds
dt.clear() 'Dt as new DATATABLE
ds.clear() 'Ds as new Dataset
this code will clear the datagridview and wil stop data duplication when populating data from database.
You can do in this way:
DataGridView1.Enable = false
DataGridView1.DataSource = Nothing
DataGridView1.Enable = true
For the Clear of Grid View Data You Have to clear the dataset or Datatable
I use this Code I clear the Grid View Data even if re submit again and again it will work
Example
Dim con As New OleDbConnection
Dim cmd As New OleDbCommand
Dim da As New OleDbDataAdapter
Dim dar As OleDbDataReader
Dim dt As New DataTable
If (con.State <> 1) Then
con.Open()
End If
dt.Clear() 'To clear Data Every time to fresh data
cmd.Connection = con
cmd.CommandText = "select * from users"
da.SelectCommand = cmd
da.Fill(dt)
DataGridView1.DataSource = dt
DataGridView1.Visible = True
cmd.Dispose()
con.Close()
You can do that only by the following 2 lines:
DataGridView1.DataSource=Nothing
DataGridView1.DataBind()
You can also try this code if you want to clear all data in your DataGridView
DataGridView1.DataSource.Clear()
Try this for a specific cell:
Datagrid.Rows(RowIndex).Cells(ColIndex).Value = DBNull.Value
DgRemolques is the name of my Data grid on WPF
dgRemolques.ItemsSource = Nothing
but i need to clean also de DataTable
dtRemolques.Clear()