Error when trying to add a row to an already existing data table and grid view - vb.net

I currently have a gridview that I am able to populate with a query. On a button click I would like to run the query again with a new value and add the new information to what is already displayed in the gridview. I am attempting to do this by copying the information that is currently in the gridview into a datatable then adding a row to the table then resetting the binding on the gridview and refreshing the gridview. The problem is I get an error when trying to add the new row (System.Data.NoNullAllowedException: 'ColumnName' does not allow nulls.
Here is the code I am trying to use for this process. Any help would be much appreciated.
Dim EpicorCM As New SqlCommand(JobSelect, EpicorCon)
EpicorCon.Open()
Dim EpicorReader As SqlDataReader = EpicorCM.ExecuteReader
Dim JobInfoTable As New DataTable
JobInfoTable = CType(dgvJobInfo.DataSource, DataTable).Copy
JobInfoTable.Rows.Add(EpicorReader)
dgvJobInfo.AutoGenerateColumns = True
dgvJobInfo.DataSource = JobInfoTable
dgvJobInfo.Refresh()
EpicorCon.Close()

You are trying to add a SqlDataReader to the Rows collection but that will not work. It only compiles because the Add() method has an overload that is params of Object.
Fortunately DataTable has a method to load a reader. Instead of this:JobInfoTable.Rows.Add(EpicorReader), do this:
JobInfoTable.Load(EpicorReader)
As an aside, commands and readers are Disposable resources so you can leak memory by not disposing of them either in Using blocks or in Finally blocks.

Related

VB.net - SQLite query response turning empty after first interaction

so I'm using SQLite in a VB.net project with a populated database. I'm using the Microsoft.Data.Sqlite.Core and System.Data.SQLite NuGet package libraries. So the problem presents when I'm trying to get the result of a query. At first the SQLiteDataReader gets the response and all the elements of the desired table. I know this cause in the debugger I have a breakpoint after the setting the object and when I check the parameters of the SQLiteDataReader object the Result View shows all the elements of my table, but as soon as I remove the mouse from the object and check it again the Result View turns out empty, without even resuming with the next line of code. Does anyone know if its a known bug or something cause Ive used this exact method of querying a table in another project and it works.
The code:
Public Function RunQuery(com As String)
If CheckConnection() Then
command.CommandText = com
Dim response As SQLiteDataReader
response = command.ExecuteReader
Dim len As Integer = response.StepCount
Dim col As Integer = response.FieldCount
Dim resp(len, col) As Object
For i = 0 To col - 1
Using response
response.Read()
For j = 0 To len - 1
resp(i, j) = response.GetValue(j)
Next
End Using
Next
Debugger with populated result view
Debugger with empty result view
edit: added the for loop to show that its not only on the debugger that the result view is empty. When using response.Read() it throws an exception "System.InvalidOperationException: 'No current row'"
As I have told you in the comment, a DataReader derived class is a forward only retrieval object. This means that when you reach the end of the records returned by the query, that object is not capable to restart from the beginning.
So if you force the debugger to enumerate the view the reader reaches the end of the results and a second attempt to show the content of the reader fails.
The other part of your problem is caused by a misunderstanding on how to work on the reader. You should loop over the Read result not using a StepCount property. This property as far as I know, is not standard and other data providers don't support it. Probably it is present in the SQLite Provider because for them it is relatively easy to count the number of records while other providers don't attempt do calculate that value for performance reasons.
However, there are other ways to read from the reader. One of them is to fill a DataTable object with its Load method that conveniently take a DataReader
Dim data As DataTable = New DataTable()
Using response
data.Load(response)
End Using
' Now you have a datatable filled with your data.
' No need to have a dedicated bidimensional array
A DataTable is like an array where you have Rows and Columns instead of indexes to iterate over.

VB.NET Clear DataTable then Fill AFTER Successfully Getting New Data

I currently use a TableAdapter to fill() a typed datatable in a typed dataset. ClearBeforeFill is set to True as the underlying data is different each time. The problem is that in the case the database is unreachable, the old data gets cleared before it knows. I want the old data to stay in the datatable (and subsequently stay displayed) in the case an error occurs retrieving from the database. Ideally, I'd still use a tableAdapter and the GetData() method instead of the Fill() method but I can't seem to figure out how to replace the current datatable with the one returned by GetData(). Tables.Remove() then Tables.Add() doesn't seem to work. Below code gives an error: "'table' argument cannot be null." & vbCrLf & "Parameter name: table"
Dim TempTbl As DS_ERecord.DT_spRefreshAndSelectStepConnectorMonitorDataTable
TempTbl = TAi_spRefreshAndSelectStepConnectorMonitor.GetData(ForceRefresh, CmbMonitorView.SelectedValue)
DSi_ERecord.Tables.Remove(DSi_ERecord.DT_spRefreshAndSelectStepConnectorMonitor)
DSi_ERecord.Tables.Add(TempTbl)

Update Listbox after inserting a row in database

I have a listbox which has a bindingsource which connects to access database. have following code which creates and adds new line to my access database and to datagrid view but changes are not updating in the listbox.
Dim drv As DataRowView = DirectCast(EQtblBindingSource.AddNew(), DataRowView)
drv.BeginEdit()
drv.Row.BeginEdit()
drv.Row("eiD") = "SS"
drv.Row("EQ_NAME") = "DUMMY"
drv.Row.EndEdit()
drv.DataView.Table.Rows.Add(drv.Row)
EQ_tblTableAdapter.Update(EQDATADataSet.EQ_tbl)
EQtblBindingSource.ResetBindings(True)
Is there a way to reflect changes immediately after i add a new row? resetbindings seems not working or another option to reload or refresh my listbox. Any idea please help.
Thanks
Make sure that the DataSource for your listbox is set to the bindingsource.
Your code can be simplified to this:
With EQtblBindingSource
.AddNew()
DirectCast(.Current, DataRowView)("eiD") = "SS"
DirectCast(.Current, DataRowView)("EQ_NAME") = "DUMMY"
.EndEdit()
End With
EQ_tblTableAdapter.Update(EQDATADataSet.EQ_tbl)

Updating Datatable as Datasource

I'm using a data table as a data source for a data grid in VB.NET.
Public Property InterimLotTable As DataTable
uxDataGridAuditSamplerView.DataSource = SamplerParent.InterimLotTable
But when I update the SamplerParent.InterimLotTable its not reflected in my dataGrid.
Here is the code where I update the Datatable.
Dim sql = String.Format("select * from CAMS.VW_BL_TAS_InterimLotData where PARENTLOT = '{0}'", ParentLot)
Dim dynaset = db.CreateDynaset(sql, DBWrapper.DynasetOptions.ORADYN_READONLY)
InterimLotTable = dynaset.CopyToDataTable()
I thought that with the databinding when I made changes to the InterimLotTable the datagrid would be updated automatically.
You're not updating InterimLotTable, you're replacing it - i.e. the property now returns a different object.
The controls that are bound to the old object don't know anything has happened, as the object they have a reference to, hasn't changed.
You could use an intermediate BindingSource, or raise an event so the UI can choose to rebind as appropriate

Refreshing Datagridview From Dataset Issue

I seem to be pulling my hair out over something that seems pretty straight forward in my eyes. I cannot get a datagridview control to update correctly after altering a dataset.
I initially populate a datagridview from a dataset and auto generate the columns no problem. However, if I regenerate my dataset with new data, the datagridview will display the new data correctly, but won't remove the old column headers.
For example, I have a query that gives me Store Name and Manager and auto populates my datagridview. Then if I change my query to just give me Store Name and Supervisor, it gives me Store Name, Manager (with blank column) and Supervisor.
I have tried datagridview.refresh() and datagridview.update() but nothing seems to work.
Here is my code:
MySQLConn.Open()
Dim ExQry As New MySqlCommand(QryStr, MySQLConn)
ExQry.CommandType = CommandType.Text
Dim da As New MySqlDataAdapter(ExQry)
dasCustomQryData.Clear() 'my dataset is called dasCustomQryData
da.Fill(dasCustomQryData, "QryData")
da.Update(dasCustomQryData, "QryData")
With dgvCustomQuery
.DataSource = Nothing
.Dock = DockStyle.Fill
.AutoGenerateColumns = True
.DataSource = dasCustomQryData
.DataMember = "QryData"
.Refresh()
.Visible = True
End With
MySQLConn.Close()
da.Dispose()
dasCustomQryData.Dispose()
So, when I want to update my datagridview, I plugin a new QryStr to the above code and it rebuilds my dataset. The dataset is getting updated, because the datagridview contains the correct data, however, my problem is that the datagridview isn't clearing the old columns that aren't populated anymore.
All help appreciated. Thanks
I would recommend you create a connection and a dataset straight from VB and the in the dataset it shows the tables. At the bottom of the tables is a standard query but u can create your own...with variables as parameters and then you can call the query through the table adapter and assign this straight to the datagridview.
That always seems to work for my programs. What sort of database are u using? Might be obvious but just to make sure, the datagridview is not bound right? Sample from one of my projects dgData.DataSource = TblEventsTableAdapter.ViewEvent(cmbEvents.SelectedItem.ToString) where dgdata is obviously datagridview. ViewEvent is a custom query created in the dataset and takes in 1argument. Hope this is of use to you
Ok, after a bit of troubleshooting and playing around with code, I found that the simple solution to this was that the datatable itself was not releasing the column headers. So even though the datagridview and the dataset was getting cleared, the datatable was still populated.
The following command solved my issue:
dt.Columns.Clear()