GUID format not recognized (when is null) - vb.net

In my application I create a function that allow the user to change the settings of the app. This settings are stored into a table 'cause there's a lot of records. Anyway, the problem's that if the settings isn't valorized yet, when the application start and load the settings from the table take of course a null GUID field and the message:
GUID format not recognized
appear. A code explaination:
Sub LoadSettings()
Using dbCon As MySqlConnection = establishConnection()
Try
dbCon.Open()
Dim MysqlCommand = New MySqlCommand("SELECT * FROM settings", dbCon)
Dim reader = MysqlCommand.ExecuteReader
For Each row In reader
Select Case row(2)
Case "company_name"
Setting.name.Text = row(3)
Case "company_email"
Setting.email.Text = row(3)
...
End Select
Next
End Sub
This function is called when the settings form is opened. If the settings aren't inserted yet, I get a message of bad format. I want to know how I can avoid this message.

You are not using the DataReader correctly. Consider this code:
Dim reader = MysqlCommand.ExecuteReader
For Each row In reader
... something
Next
MysqlCommand.ExecuteReader returns a DataReader object, but it is not - nor does it contain - a row collection you can iterate. If you hold the mouse over row you should see that it is a Data.Common.DataRecordInternal object which does have an Item property but a reference like row(2) will only compile with Option Strict Off.
Used correctly, when you Read a row the data in that internal object is available via the indexer (Item) and the various Getxxxxx() methods. This just prints the Id and Name from a table in a loop. I cant quite tell what you are trying to do with your results...it sort of looks like a Name/Value pair type thing maybe.
Dim SQL = "SELECT * FROM Demo"
Using dbcon = GetMySQLConnection(),
cmd As MySqlCommand = New MySqlCommand(SQL, dbcon)
dbcon.Open()
Using rdr As MySqlDataReader = cmd.ExecuteReader
If rdr.HasRows Then
Do While rdr.Read()
Console.WriteLine("{0} - {1}", rdr("Id").ToString, rdr("Name").ToString)
Loop
End If
End Using ' dispose of reader
End Using ' dispose of Connection AND command object
Alternatively, you could fill a DataTable and iterate the rows in that. Seems 6:5 and pick-em whether that would gain anything.
Note also that the Connection, Command and DataReader objects are properly disposed of when we are done using them.

Related

Issue Comparing Access Column

Can someone please explain to me when the "size" column wont work for comparison but I can replace the ID column in my code and it works perfectly fine. Perhaps my formatting of the access database column for Size isnt correct?
I am basically just trying to see if the key and value in my dictionary match the conditions in the access database and if so to write one text, if not write another. The error I keep getting when I have size in my code is:
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll IErrorInfo.GetDescription failed with E_FAIL(0x80004005).
For Each KeyPair In dict
Dim key As String
Dim value As Integer
key = KeyPair.Key
value = KeyPair.Value
Dim sqlQry As String
sqlQry = "SELECT Item, Size FROM [Table] WHERE Item = '" & key & "'AND Size>" & value & " "
Console.WriteLine(sqlQry)
Dim topDecision As String
Dim cmd As OleDbCommand
cmd = New OleDbCommand(sqlQry, myconnection)
Dim myreader As OleDbDataReader
myreader = cmd.ExecuteReader()
If myreader.Read() Then
topDecision = "Order"
Else
topDecision = "Dont"
End If
myreader.Close()
Next
Connections and some other database objects provided by ADO.net use unmanaged code internally. They provide a .Dispose method where they release these resources. It is up to the coder to call the .Dispose method. Fortunately, .net provides Using...End Using blocks that handle this for us. Connections, commands and readers should be declared in the method where they are used so they can be properly closed and disposed.
Don't concatenate strings to build sql queries. Use parameters to avoid sql injection. We only need a single command and a single ParametersCollection. Only the values of the parameters change inside the loop.
A special note for OleDb parameters. The names of the parameters are ignored. The position of the parameter in the sql query should match the order that they are added to the ParametersCollection.
Declare KeyPair As KeyValuePair so you can access .Key and .Value properties.
I used a StringBuilder to collect the messages from your code. A StringBuilder is mutable (changeable) whereas a String is not. If I used a String the compiler would have to throw away a string and create a new one on each iteration. The garbage collector would be kept busy.
I used an interpolated string indicated by the $ before the string. It allows us to insert variables directly into the string if they are surrounded by braces { }.
If you follow this sample, be sure the text box at the end has Multiline = True.
Private Sub OPCode()
Dim sqlQry = "SELECT Item, Size FROM [Table] WHERE Item = #Key AND Size > #Value;"
Dim sb As New StringBuilder
Using cn As New OleDbConnection("Your connection string"),
cmd As New OleDbCommand(sqlQry, cn)
cmd.Parameters.Add("#Key", OleDbType.VarChar, 100)
cmd.Parameters.Add("#Value", OleDbType.Integer)
cn.Open()
For Each KeyPair As KeyValuePair(Of String, Integer) In dict
cmd.Parameters("#Key").Value = KeyPair.Key
cmd.Parameters("#Value").Value = KeyPair.Value
Dim topDecision As String
Using myreader = cmd.ExecuteReader()
If myreader.Read() Then
topDecision = "Order"
Else
topDecision = "Dont Order"
End If
End Using
sb.AppendLine($"{KeyPair.Key} - {topDecision}")
Next
End Using
TextBox1.Text = sb.ToString
End Sub

Autofill textboxes from access database based on one text box value

I have 3 text boxes and based on Customer Name suggestion other 2 boxes should be auto filled
I am new to database so I am finding codes on internet and trying to implement it but it
is not working. So please help me with this.
I am working in for Windows Form Application in visual basic.
Private Sub AutoComplete()
'sql = "Select * FROM Table1 where CustomerName='" & custnm.Text & "'"
com = New OleDbCommand(sql, con)
reader = com.ExecuteReader()
Dim autoComp As New AutoCompleteStringCollection()
While reader.Read()
autoComp.Add(reader("CustomerName"))
autoComp.Add(reader("ContactNO"))
End While
reader.Close()
custnm.AutoCompleteMode = AutoCompleteMode.Suggest
custnm.AutoCompleteSource = AutoCompleteSource.CustomSource
custnm.AutoCompleteCustomSource = autoComp
contactno.AutoCompleteMode = AutoCompleteMode.Suggest
contactno.AutoCompleteSource = AutoCompleteSource.CustomSource
contactno.AutoCompleteCustomSource = autoComp
wcontno.AutoCompleteMode = AutoCompleteMode.Suggest
wcontno.AutoCompleteSource = AutoCompleteSource.CustomSource
wcontno.AutoCompleteCustomSource = autoComp
End Sub
This is only a partial solution to straighten out your database code. It is too much code to put in a comment.
Keep your database objects local so you can control when they are closed and disposed. Objects that expose a .Dispose method may have unmanaged resources that need to be released. A Using...End Using block will handle this for you even if there is and error.
Always use Parameters to avoid sql injection which can damage your database. Also it makes the sql string easier to write. You will need to check your database for the proper datatype because I had to guess.
A DataReader uses an open connection until it is done. You don't want to hold your connection open while you use the data so I chose a DataTable. Just load it and pass it off to where you want to use it. The connection and command are closed and disposed.
I wasn't sure why you combined the data in a single AutoCompleteStringCollection. It seems that one for each combo box would be better. They are form level variables so you can used them in another method to attach to a combo box.
I think you need to look into BindingSource and BindingNavigator to sync the combo boxes.
Private Function GetData() As DataTable
Dim dt As New DataTable
Using con As New OleDbConnection("Your connection string"),
com As New OleDbCommand("Select * FROM Table1 where CustomerName= #Name;", con)
com.Parameters.Add("#Name", OleDbType.VarChar).Value = custnm.Text
con.Open()
dt.Load(com.ExecuteReader)
End Using
Return dt
End Function
Private autoCompName As New AutoCompleteStringCollection()
Private autoCompNO As New AutoCompleteStringCollection()
Private Sub FillAutoCompleteCollection()
Dim dt = GetData()
For Each row As DataRow In dt.Rows
autoCompName.Add(row("CustomerName").ToString)
autoCompNO.Add(row("ContractNO").ToString)
Next
End Sub

Visual Studio - multiple Table to multiple DataGridView with MS Access

how can i populate multiple table into multiple DataGridview?
for example i have 3 tables which is table1, table2 and table3, and in my form i have 3 dataGridView with name of dataGridView1, dataGridView2 and dataGridView3. i found this solution Updating an Access Database via a DataGridView Using OLEDB in VB.NET as a result of my code.
function loadDatabaseDataToGridView
Dim msAccessFilePath As String
Dim con As New OleDbConnection
Dim dataTable, dataTable2, dataTable3, dataTable4 As New DataTable
Dim olebDataAdapter As New OleDbDataAdapter
Dim da As New OleDbDataAdapter
Dim dataSet As New DataSet
Private Sub loadDatabaseDataToGridView()
Try
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & msAccessFilePath
dataSet.Tables.Add(dataTable)
olebDataAdapter = New OleDbDataAdapter("Select * from table1", con)
olebDataAdapter.Fill(dataTable)
olebDataAdapter = New OleDbDataAdapter("Select * from table2", con)
olebDataAdapter.Fill(dataTable2)
olebDataAdapter = New OleDbDataAdapter("Select * from table3", con)
olebDataAdapter.Fill(dataTable3)
DataGridView1.DataSource = dataTable.DefaultView
DataGridView2.DataSource = dataTable2.DefaultView
DataGridView3.DataSource = dataTable3.DefaultView
Dim cb = New OleDbCommandBuilder(olebDataAdapter)
cb.QuotePrefix = "["
cb.QuoteSuffix = "]"
MessageBox.Show("Successfull")
Catch ex As Exception
MessageBox.Show("Failed")
con.Close()
End Try
con.Close()
End Sub
function SaveChanges
'Perform this on Button Save is Click
Private Sub saveChanges()
olebDataAdapter.Update(dataSet)
End Sub
This code is working as excpected, it is populating the data from MS Access file but when i clicked the button save to save the changes on edited data, an error has occurred.
THE ERROR:
Concurrency violation: the UpdateCommand affected 0 of the expected 1 records
anyone does know how to properly implement of what i am trying to achieve? Thank You Very Much!!!
Each DataAdapter object only has a single UpdateCommand, so you'll need one for each data table. If it runs the update command and no rows are updated (because the update command is actually for a table that you haven't changed) then you'll get the Concurrency Violatation.
It actually gets more complicated than this if your tables are related as the order that inserts, updates and deletions occur can be critical.
If you create a Strongly Typed Dataset it generates designer code that includes a TableAdapterManager class and all of the required data adapters. It might be worth playing around with this just so that you can see how the generated code works.
Just a note, the 'Concurrency violation' exception is actually there so that you can design an update command that will only succeed if the contents of the record in the database match the data held locally (to prevent you from overwriting another user's changes). Search for Optimistic Locking for more details.

Populate column values from MS Access database into VB .Net Combo-Box dropdown values?

I am accessing data from Access MDB file using my application developed in VB .net 2010.
I want to get values from a particular table-column to be populated in a Combo Box dropdown.
I followed a similar thread # C# Adding data to combo-box from MS Access table but as the code is in C#, I was not able to successfully implement it. And reverted back to my previous code.
Because the Table will be updated by another application as well, every time I use my utility I need to get the latest data from that table. Hence I would like to have a feature that could get all available id from table.
Below is what I have been trying to do..
'below declared at class level.
' Dim cnnOLEDB As New OleDbConnection
' Dim cmdOLEDB As New OleDbCommand
cnnOLEDB.Open()
cmdOLEDB.CommandText = "select unique_id from tag_data"
cmdOLEDB.Connection = cnnOLEDB
Dim rdrOLEDB2 As OleDbDataReader = cmdOLEDB.ExecuteReader
If rdrOLEDB2.Read = True Then
TagComboBox1.DataSource = rdrOLEDB2.Item(0).ToString
TagComboBox1.ValueMember = "unique_id"
TagComboBox1.DisplayMember = "unique_id"
End If
rdrOLEDB2.Dispose()
rdrOLEDB2.Close()
cnnOLEDB.Close()
I would recommend filling a DataTable with your query. Then you can set the DataSource of the combobox, ValueMember & the DisplayMember.
Dim dt As New DataTable
Dim query As String = "select unique_id from tag_data"
Using connection As New OleDbConnection("your connection string")
Using command As New OleDbCommand(query, connection)
Using adapter As New OleDbDataAdapter(command)
connection.Open()
adapter.Fill(dt)
connection.Close()
End Using
End Using
End Using
If dt.Rows.Count > 0 Then
TagComboBox1.DataSource = dt
TagComboBox1.ValueMember = "unique_id"
TagComboBox1.DisplayMember = "unique_id"
End If

vb.net cycle through query results

I am familiar with the VB6 ADO way of dealing with SQL queries and looping through the record set results.
However, what is the correct way to query a server, cycle through the results, and dispose of my query in VB.Net? All the ways I have been using seem to be unstable and crash randomly.
I have been using the following code:
Public Function GetSQLTable(ByVal strSQL As String) As DataTable
Dim table As New DataTable
Dim adapt As SqlDataAdapter
Try
adapt = New SqlDataAdapter(strSQL, gconIntegration)
adapt.Fill(table)
Catch ex As Exception
LogError("GetSQLTable: " & ex.ToString(), "SQL: " & strSQL)
End Try
Return table
End Function
And using it like this:
Dim dt As DataTable
Dim lngRow As Long
Dim current As DataRow
Dim lngContact As long
Try
dt = GetSQLTable(strSQL)
For lngRow = 0 To dt.Rows.Count - 1
current = dt.Rows.Item(lngRow)
lngContact = current.Item("indvid")
DoSomething(lngContact)
Next
Catch ex As Exception
LogError("FindContact: " & ex.ToString(), "SQL: " & strSQL)
lngContact = -1
Finally
current = nothing
dt = nothing
I suspect the problem has to do with how you manage your gconIntegration connection. You're trying too hard to keep using that same connection. It would be helpful to see where it lives.
Better to get "new" connections from the pool and let .Net worry about it for you.
Also, your generic "GetSQLTable" code is missing an important part: it makes no allowance for setting parameters, which tells me you're building them directly into your query strings. That's a recipe for disaster: it will lead to Sql injection security holes.
One more thing: don't set objects to Nothing in .Net. Either dispose them if needed or let them fall out of scope on their own.
Here's my normal method for pulling back a datatable from a datatable:
Function GetSomeData(ByVal Table2ID As Integer)
Dim result As New DataTable
Dim sql As String = "SELECT Column1,Column2 FROM [Table1] WHERE Table2ID= #Table2ID"
Using cn As New SqlConnection( GetConnectionString() ), _
Using cmd As New SqlCommand(sql, cn)
cmd.Parameters.Add("#Table2ID", SqlDbType.Int).Value = Table2ID
Using rdr As SqlDataReader = cmd.ExecuteReader()
result.Load(rdr)
End Using
End Using
return result
End Function
Some notes on that code:
The Using statement will guarantee that the associated object is disposed at the corresponding End Using.
The query parameters are kept strongly typed, and never substituted directly into the query string, even when they are transmitted to the server. Sql Data and Sql Code never mix.
You do need a separate function for each query you need to send. This is really a good thing, as it leads into building a strongly-typed interface for your database. Ideally all of these functions are in the same class, and the GetConnectionString function is private to that class. No database access happens outside of this data layer.