How to refresh GridView after Insert - sql

I'm fairly new to Vb, and my task is to create programmaly those whole process, creating SqlDataAdapter, DataTable, DataSet. However I still can't manage the right things to do and in what order. I can retrieve, Update, Delete and sometimes my Insert works but I can't get the fresh data from my DataBase straight after the insert. Also, I want to mention I have a GUID as UniqueIndentifier in my SQL Table which need to be populated with the rest of the data in the GridView. Thank you
I have tried to put SELECTCOMMANDE and call the method FILL after the Insert, also to clear the the DataSet, put the gridControl.Datasource = Nothing, lastly I tried to Update my SqlDataAdapter. None of those methods worked for me....:(
gridView.AddNewRow()
gridView.UpdateCurrentRow()
'sqlDa.SelectCommand = New SqlCommand(str_select_command, connection)
'sqlDa.Fill(dataS, "Representants")
connection.Close()
'gridControl.RefreshDataSource()
'dataS.Clear()
'dataS.Tables.Remove("Representant")
'sqlDa.Update(dataS.Tables(0))
''sqlDa.Fill(dataS, "Representants")
'gridControl.DataSource = Nothing
'gridControl.DataSource = dataS.Tables(0)
'gridView.PopulateColumns()
'gridView.RefreshData()
Try
connection.Open()
Dim Command = New SqlCommand("INSERT INTO TEST (prenom, nom, id_cie_12) " & "VALUES (#prenom, #nom, #id_cie_12)", connection)
Command.Parameters.Add("#prenom", SqlDbType.NChar, 20, "prenom")
Command.Parameters.Add("#nom", SqlDbType.NChar, 20, "nom")
Command.Parameters.Add("#id_cie_12", SqlDbType.NChar, 10, "id_cie_12")
sqlDa.InsertCommand = Command
gridView.RefreshData()
bbiButton.Enabled = False
Catch ex As Exception
MsgBox(ex.ToString)
Finally
connection.Close()
End Try
I'm expecting the data updated from the DataBase shown in the GridView.

Public Class Form1
Sub filterrecords(ByVal sender As String)
cmd.Connection = cn
cmd.CommandText = "SELECT * FROM Table1"
Dim da = New SqlDataAdapter(cmd)
Dim dt As New DataTable
da.Fill(dt)
DataGridView1.DataSource = dt
Dim imgc As New DataGridViewImageColumn
imgc = DataGridView1.Columns(5)
imgc.ImageLayout = DataGridViewImageCellLayout.Stretch
End Sub
then Paste in Form Load
filterrecords("")
cmd.ExecuteNonQuery()
cn.Close()
and paste Here
filterrecords("")

Related

VB.NET How to correctly loop through a result set

I have looked at many different code snippets on this site looking that would show me how to do something that should be fairly simple once I have the knowledge.
I want to query a database table for an array of values and then populate a combobox with those results.
Here is what I have so far:
Public Sub getMachines()
Try
Dim SQL As String = "SELECT MachineName from machine"
Form1.machineName.DisplayMember = "Text"
Dim tb As New DataTable
tb.Columns.Add("Text", GetType(String))
Using cn As New MySqlConnection(ConnectionString)
Using cmd As New MySqlCommand(SQL, cn)
For Each cmd As String In cmd
'I want to add each value found in the database to "tb.Rows.Add"
'tb.Rows.Add(???)
Next
Form1.machineName.DataSource = tb
cn.Open()
cmd.ExecuteNonQuery()
End Using
cn.Close()
End Using
Catch ex As MySqlException
MsgBox(ex.Message)
End Try
End Sub
I proceeded much like you did. I used the Load method of the DataTable. It is not necessary to set the column name and type. The name of the column is taken from the Select statement and the datatype is inferred by ADO.net from the first few records.
Luckily a DataTable can be an Enumerable using the .AsEnumnerable method. Then we can use Linq to get all the values from the MachineName column. Calling .ToArray causes the Linq to execute. If you hold your cursor over names on this line you will see that the datatype is String(). Just what we need to fill a combo box.
Code for a class called DataAccess
Private ConnectionString As String = "Your Connection String"
Public Function GetMachineNames() As String()
Dim tb As New DataTable
Dim SQL As String = "SELECT MachineName from machine;"
Using cn As New MySqlConnection(ConnectionString)
Using cmd As New MySqlCommand(SQL, cn)
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
Dim names = dt.AsEnumerable().Select(Function(x) x.Field(Of String)("MachineName")).ToArray()
Return names
End Function
In the form load you combo box like this.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim DatAcc As New DataAccess()
Dim arr = DatAcc.GetMachineNames()
machineName.DataSource = arr
End Sub
If you just want the MachineName to be displayed in the ComboBox, then just use that as the DisplayMember; don't bother creating another column called Text.
Public Sub getMachines()
Try
Dim cmd As String = "SELECT MachineName from machine"
Dim ds As New DataSet()
Using con As New MySqlConnection(ConnectionString)
Using da As New MySqlDataAdapter(cmd, con)
da.Fill(ds)
With Form1.machineName
.DisplayMember = "MachineName"
.ValueMember = "MachineName"
.DataSource = ds
End With
End Using
End Using
Catch ex As MySqlException
MsgBox(ex.Message)
End Try
End Sub
I'll show a few examples, including using parameters, since that is important.
First up, a quick translation to run the existing query and loop through the results:
Public Sub getMachines()
Try
Dim SQL As String = "SELECT MachineName from machine"
Using cn As New MySqlConnection(ConnectionString), _
cmd As New MySqlCommand(SQL, cn)
cn.Open()
Using rdr As MySqlDatareader = cmd.ExecuteReader
While rdr.Read()
Form1.machineName.Items.Add(rdr("MachineName"))
End While
End Using
End Using
Catch ex As MySqlException
MsgBox(ex.Message)
End Try
End Sub
But better practice for a method like this is to isolate data access for the UI. This method should return results to the caller, which can decide what do with them. So I'll show two methods: one to get the data, and the other to loop through it and set up the combobox:
Private Function GetMachines() As DataTable
'No try/catch needed here. Handle it in the UI level, instead
Dim SQL As String = "SELECT MachineName from machine"
Dim result As New DataTable
Using cn As New MySqlConnection(ConnectionString), _
cmd As New MySqlCommand(SQL, cn),
da As New MySqlDataAdapter(cmd)
da.Fill(result)
End Using
Return result
End Function
Public Sub LoadMachines()
Try
For Each item As DataRow in getMachines().Rows
Form1.machineName.Items.Add(item("MachineName"))
Next
Catch ex As MySqlException
MsgBox(ex.Message)
End Try
End Sub
Or, we can use DataBinding:
Private Function GetMachines() As DataTable
Dim SQL As String = "SELECT MachineName from machine"
Dim result As New DataTable
Using cn As New MySqlConnection(ConnectionString), _
cmd As New MySqlCommand(SQL, cn),
da As New MySqlDataAdapter(cmd)
da.Fill(result)
End Using
Return result
End Function
Public Sub LoadMachines()
Try
Form1.machineName.DisplayMember = "FirstName";
Form1.machineName.ValueMember = "City"
Form1.machineName.DataSource = GetMachines()
Catch ex As MySqlException
MsgBox(ex.Message)
End Try
End Sub
If you ever want to use a filter, you might do this (notice the overloading):
Private Function GetMachines(ByVal machineFilter As String) As DataTable
Dim SQL As String = "SELECT MachineName from machine WHERE MachineName LIKE #Filter"
Dim result As New DataTable
Using cn As New MySqlConnection(ConnectionString), _
cmd As New MySqlCommand(SQL, cn),
da As New MySqlDataAdapter(cmd)
'Match the MySqlDbType to your actual database column type and length
cmd.Parameters.Add("#Filter", MySqlDbType.VarString, 30).Value = machineFilter
da.Fill(result)
End Using
Return result
End Function
Private Function GetMachines(ByVal machineFilter As String) As DataTable
Return GetMachines("%")
End Function
Query parameters like that are very important, and if you were doing string concatenation to accomplish this kind of thing on your old platform, you were doing very bad things there, too.
Finally, let's get fancy. A lot of the time, you really don't want to load an entire result set into RAM, as is done with a DataTable. That can be bad. Instead, you'd like be able to stream results into memory and only work with one at a time, minimizing RAM use. In these cases, you get to play with a DataReader... but returning a DataReader object from within a Using block (which is important) doesn't work that well. To get around this, we can use functional programming concepts and advanced language features:
Private Iterator Function GetMachines(ByVal machineFilter As String) As IEnumerable(Of String)
Dim SQL As String = "SELECT MachineName from machine WHERE MachineName LIKE #Filter"
Using cn As New MySqlConnection(ConnectionString), _
cmd As New MySqlCommand(SQL, cn)
'Match the MySqlDbType to your actual database column type and length
cmd.Parameters.Add("#Filter", MySqlDbType.VarString, 30).Value = machineFilter
cn.Open()
Using rdr As MySqlDatareader = cmd.ExecuteReader
While rdr.Read()
Dim result As String = rdr("MachineName")
Yield Return result
End While
End Using
End Using
Return result
End Function
Private Function GetMachines() As IEnumerable(Of String)
Return GetMachines("%")
End Function

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

Check before dataser make changes

I use datagridview and populate it using dataset as follows:
Private GetGeschaftDataSet As New DataSet
Public Function GetDataSet() As DataSet Implements IDAL.GetDataSet
Dim strcon = New AppSettingsReader().GetValue("ConnectionString", GetType(System.String)).ToString()
Using con As New SqlConnection(strcon)
Using cmd As New SqlCommand("SELECT * FROM T_Marke", con)
con.Open()
' Create a data adapter in the method and throw it away afterwards
Using GetProjectsDataAdapter = New SqlDataAdapter(cmd)
GetProjectsDataAdapter.Fill(GetGeschaftDataSet, "trial1")
End Using
End Using
End Using
Return GetGeschaftDataSet
End Function
when user ends work with that i save changes to db like this:
Public Sub MakeChangesDataSet() Implements IDAL.MakeChangesDataSet
If Not GetGeschaftDataSet.HasChanges Then
MessageBox.Show("No changes to save", "Informacja", MessageBoxButtons.OK, MessageBoxIcon.Warning)
Else
Dim i As Integer
Try
Using MyConnection = New SqlConnection(strcon)
Using cmd As New SqlCommand("SELECT * FROM T_Marke", MyConnection)
MyConnection.Open()
' Create a data adapter in the method and throw it away afterwards
Using GetProjectsDataAdapter = New SqlDataAdapter(cmd)
Dim cmdbuilder As New SqlCommandBuilder(GetProjectsDataAdapter)
i = GetProjectsDataAdapter.Update(GetGeschaftDataSet, "trial1")
End Using
End Using
End Using
MessageBox.Show("Updated" & i & " marke", "Informacja", MessageBoxButtons.OK, MessageBoxIcon.Information)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End Sub
However i would like to check whether to not duplicate data, in this case if my table contains columns: Id and Name - i don't want to update if user placed already existing Name. How to achieve that or should i do the check on datagrid level?
There some ways to do this.
Open a connection and select count all rows with that name and if is zero in the same connection execute the insert.
Using a stored procedure which will do all the above.
Create a unique index on Name column
I would use the third.

How to refresh GridView's data after update or delete operation in case of , GridControl.datasource = Datatable in Devexpress

I have a devexpress gridview that is related to a table in a sql server database. I am trying to refresh the gridview right after performing a delete but nothing I've tried so far has worked. (I've verified that the delete operation has worked in the table). I've tried 3 ways of updating the gridview but nothing has worked:
GridControl1.Refresh()
GridView1.RefreshData()
GridControl1.RefreshDataSource()
GridView1.RefreshEditor(True)
Here is the complete code of the whole operation:
Using cnn As New SqlConnection(FrmGeneralConfig.GetInstance.getConnection())
Try
cnn.Open()
Dim daDelete As New SqlDataAdapter
Dim command As SqlCommand = New SqlCommand("DELETE FROM Client_Excepte_Charge_Min WHERE ClientNo = #ClientNo", cnn)
command.Parameters.AddWithValue("#ClientNo", clientNo)
daDelete.DeleteCommand = command
daDelete.DeleteCommand.ExecuteNonQuery()
cnn.Close()
Catch ex As Exception
MessageBox.Show("Erreur: " & ex.Message)
Finally
GridControl1.Refresh()
GridView1.RefreshData()
GridView1.RefreshEditor(True)
End Try
End Using
You need to update your DataTable after deleting the rows in server.
Here is example:
Using cnn As New SqlConnection(FrmGeneralConfig.GetInstance.getConnection())
Try
cnn.Open()
Dim command As SqlCommand = New SqlCommand("DELETE FROM Client_Excepte_Charge_Min WHERE ClientNo = #ClientNo", cnn)
command.Parameters.AddWithValue("#ClientNo", clientNo)
command.ExecuteNonQuery()
dtExceptions.Clear()
Using adapter As New SqlDataAdapter()
Dim selectCommand = New SqlCommand("SELECT * FROM Client_Excepte_Charge_Min", cnn)
adapter.SelectCommand = selectCommand
adapter.Fill(dtExceptions)
End Using
cnn.Close()
Catch ex As Exception
MessageBox.Show("Erreur: " & ex.Message)
End Try
End Using

Sql Adapter . How to update a DataTable with no primary keys

This table that I have has been created with no primary keys. There is a reason why its been created with no keys. It is something like a product and customer relationship table. So after the standard procedure of using SqlDataAdapter and DataSet along with DataTable to fill the DataGrid I have an error updating the changes.
I have been working on several forms using DataGrid' but they all work fine due to the fact the table have primary keys. I tried adding a composite key but it didn't work. So below is my code for theDataSet` and the update code which works for other forms.
The update codes:
cmdbuilder = New SqlCommandBuilder(adapter)
If primaryDS IsNot Nothing Then
primaryDS.GetChanges()
'update changes
adapter.Update(primaryDS)
MsgBox("Changes Done")
'refresh the grid
CMDrefresh()
End If
And here is the coding for the DataTable I tried adding 5 composite keys. So how do you update with this problem?
Try
myconnection = New SqlConnection(strConnection)
myconnection.Open()
adapter = New SqlDataAdapter(StrQuery, myconnection)
adoPrimaryRS = New DataSet
adapter.Fill(primaryDS)
Dim mainTable As DataTable = primaryDS.Tables(0)
DataGrid.AutoGenerateColumns = False
mainTable.PrimaryKey = New DataColumn() {mainTable.Columns(0), _
mainTable.Columns(1), _
mainTable.Columns(2), _
mainTable.Columns(3), _
mainTable.Columns(4)}
bndSrc.DataSource = mainTable
DataGrid.DataSource = bndSrc
gDB.Connection.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
So I decided to go on and answer my question. You cant use the code above to up but you can still insert the new rows. Since Dataset is a memory if the whole database was removed it would not be effect. So the answer to how to update a table with no primary key or composite keys it to trancute it then insert all rows from the Dataset Table in to it. Here is the Code for Trancute and The one below is to insert. With these the table gets new values. It works for me.
Dim con As New SqlConnection
Dim cmd As New SqlCommand
con.ConnectionString = strConnection
Dim strSql As String
'MsgBox(con.ConnectionString.ToString)
Try
con.Open()
cmd = New SqlCommand
cmd.Connection = con
strSql = "TRUNCATE TABLE Table1"
cmd.CommandText = strSql
cmd.ExecuteNonQuery()
cmd.Dispose()
cmd = Nothing
con.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
So here is The Insert code.
Dim con As New SqlConnection
Dim cmd As New SqlCommand
Dim strSql As String
con.ConnectionString = strConnection
For i As Integer = 0 To grdDataGrid.Rows.Count - 1
'MsgBox(con.ConnectionString.ToString)
con.Open()
cmd = New SqlCommand
cmd.Connection = con
Try
strSql = "INSERT INTO Table1 ( [one], [two], [three], [four], [five] )" +_
"VALUES (#one, #two, #three ,#four ,#five )"
cmd.CommandText = strSql
cmd.Parameters.AddWithValue("#one", grdDataGrid.Rows(i).Cells(2).Value)
cmd.Parameters.AddWithValue("#two", grdDataGrid.Rows(i).Cells(0).Value)
cmd.Parameters.AddWithValue("#three", grdDataGrid.Rows(i).Cells(1).Value)
cmd.Parameters.AddWithValue("#four", grdDataGrid.Rows(i).Cells(3).Value)
cmd.Parameters.AddWithValue("#five", grdDataGrid.Rows(i).Cells(4).Value)
cmd.ExecuteNonQuery()
cmd.Dispose()
cmd = Nothing
con.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Next
CMDrefresh()