vb net SQl query problem - mysql

im trying to retrieve some data using a reader in vb.net. I dont have any issue retrieving certain columns of the data for each row but i want to retrieve all data in each row. I've tried a couple of different things with the getstring() command but it isnt working and i cant seem to find any help googling the issue. my code is this
Private Function QueryDown(ByVal queryString)
Dim returnInfo As New StringBuilder
Try
Dim newQuery As String() = Split(queryString, ":")
For Each Query In newQuery
Dim cmd As New MySqlCommand(Query, connection1)
Dim reader As MySqlDataReader
reader = cmd.ExecuteReader()
While reader.Read()
For a = 0 To reader.FieldCount
Dim strng As String = reader.GetString(a)
returnInfo.Append(strng & ",")
Next
returnInfo.Append(";")
End While
reader.Close()
Next
Catch ex As Exception
console("Error with MySQL: " & ex.Message)
Return ex.Message
End Try
Return returnInfo.ToString
End Function
sorry the error i get when using this code is
There is already an open DataReader
associated with this Connection which
must be closed first
but if i change getstring(a) to getstring(1) everything is fine, im confused.
any help here would be great, i want to formatted code to come back column,column,coloumn;nextrow, as you can see (i hope). Because each of my table has a different amount of coloumns and i want to be able to use the same function for each one. thanks again.

Upper limit is reader.FieldCount - 1 not reader.FieldCount in:
For a = 0 To reader.FieldCount - 1
when a reaches reader.FieldCount there is an exception => reader.Close() is not executed => I suppose you call this function (or another) to open a new reader with the same connection => error.
When you call getstring(1) its working because 1 is within [0, FieldCount-1]
Update:
As #Zach Green said, try to always use using when ever possible which is a replacement for try...finally{ .Dispose() }: the dispose in finallyis applied to object beeing "used" and calling for DataReader/DataConnection it will call .Close() for you.

Related

How can I get the usernames in the account?

I'm making a VB.Net application which connects to a MySql database.
My application has many Accounts, and each account has several Users. I want to show this information, but the application just shows the first user of each account.
This is the code:
Public Function id(Label2 As String) As Double
Using connection = Getconnection()
connection.Open()
Using commandid = New MySqlCommand
commandid.Connection = connection
commandid.CommandText = "SELECT *FROM player.player
Where player.account_id=" & testString & V
Dim read = commandid.ExecuteReader
If read.HasRows Then
While read.Read
ActivateUser.namecharacter = read.GetString(2)
ActivateUser.job = read.GetString(3)
End While
read.Dispose()
Return True
Else
MessageBox.Show(" no ")
Return False
End If
connection.Close()
connection.Dispose()
End Using
End Using
End Function
How can I fix this to show all the users in the account?
Just create you connection in the method where you use it. Get rid of GetConnection just use a class level variable for the connection string.
Don't open a connection until directly before you use it.
You can include the command in the same using block by adding a comma at the end of the first line. Commands also need to be disposed. The command constructor can take the CommandText and the Connection as parameters.
What datatype is account_id in the database? I am going to guess it is a string type. Is V a variable or is it meant to be the string "V"? I am going to guess a hardcoded string. Where does testString come from? I am going to guess Label2 (terrible non-descriptive name) is teststring.
Never concatenate strings for you sql. Always use parameters.
A reader also needs to be closed and disposed so use Using blocks. The whole idea of accessing the database is to get in and out as quickly as possible. Don't set properties of ActivateUser and never show a message box. The user could have gone to lunch and your connection is left flapping in the breeze.
You have the datatype of your function as Double but your return statements have Booleans. Won't work.
It is not necessary to close and dispose the connection. The End Using does that.
Private ConStr As String = "Your connection string"
Public Function id(Label2 As String) As DataTable
Dim dt As New DataTable
Using connection As New MySqlConnection(ConStr),
commandid As New MySqlCommand("SELECT *FROM player Where account_id= #TestString;", connection)
commandid.Parameters.Add("#TestString", MySqlDbType.VarChar).Value = Label2 & "V"
connection.Open()
Using reader = commandid.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Then back in the User Interface code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dt = id(Label2.Text)
If dt.Rows.Count > 0 Then
ActivateUser.namecharacter = dt(0)(2).ToString
ActivateUser.job = dt(0)(3).ToString
Else
MessageBox.Show(" no ")
End If
End Sub
This makes a good separation of from your database code.

Redefining/Re-setting parameters in MySQL query

I have the following code for inserting data into a table using a MySQL query in VB.NET
Dim MySqlCmdStr = "INSERT INTO tb_idlink(id1,id2) " &
"VALUES (#par1,#par2)"
MySqlCmd.CommandText = MySqlCmdStr
Dim checkedItem As Object
For Each checkedItem In CheckedListBox_1.CheckedItems
Try
MySqlCmd.Connection = MySqlConn
With MySqlCmd
.Parameters.AddWithValue("#par1", currentID)
.Parameters.AddWithValue("#par2", checkedItem.ToString())
End With
MySqlConn.Open()
MySqlCmd.ExecuteNonQuery()
MySqlConn.Close()
Catch ex As MySqlException
MessageBox.Show(ex.Message)
End Try
Next
My problem is if I have more than one box checked in CheckedListBox_1 then on the second loop an exception that says something like "parameter #par1 already defined". Is there a way I can re-define it? I'm not entirely familiar with the whole API.
Also, I'm not 100% sure if looping it is the best way to do this, but it's the first thing that popped into my head. Feel free to suggest an alternative way of doing this.
You dont redefine the parameters, you just supply a new value:
Dim SQL = "INSERT INTO tb_idlink (id1,id2) VALUES (#par1,#par2)"
Using dbcon As New MySqlConnection(MySQLConnStr)
Using cmd As New MySqlCommand(SQL, dbcon)
' define the parameter names and types
cmd.Parameters.Add("#par1", MySqlDbType.Int32)
cmd.Parameters.Add("#par2", MySqlDbType.Int32) ' ????
dbcon.Open()
For Each checkedItem In CheckedListBox1.CheckedItems
' provide the parameter values
cmd.Parameters("#par1").Value = currentID
cmd.Parameters("#par2").Value = Convert.ToInt32(checkedItem)
cmd.ExecuteNonQuery()
Next
End Using
End Using
Your code appears to reuse a global connection, that is ill-advised. The above uses Using blocks to create, use and and dispose of the DbConnection and DbCommand objects in the smallest scope possible
You should favor Add rather than AddWithValue so you can specify the datatype rather than forcing the the DB Provider guess and reduce the chance of data type mismatch errors.
These datatypes are a guess; CurrentId is not defined anywhere and given the names, both seem to be integers not strings.

Show image using function

I'm new to VB. NET so please bear with me. In the code below, I have a picture box in my main form and I want the selected query profile_picture to show in the picture box but I have no idea what the function should return
Public Sub ShowPicture(ByVal username As String)
user = username
Dim dsSearch As DataSet
ModuleQuery.Showpic(username)
Dim dSearch As Byte() = DirectCast(dr("Photo"), Byte())
Dim ms As New MemoryStream(dsSearch)
prof_pic.Image = Image.FromStream(ms)
End Sub
This is a module which includes all SELECT queries so that it won't be messy.
I want to call a function but I don't know what to return so that I can show the image
Public Function Showpic(ByVal user As String)
Dim FunctionErrorState As Boolean = False
Dim InsertError As Boolean = False
Dim CloseError As Boolean = False
Dim dsData As New DataSet
Dim bite As Byte()
Try
openDB()
'MyADOConnection.Open()
Dim myQuery As String = "SELECT profile_picture FROM coa.register WHERE username = '" & user & "'"
Dim myCommand As New MySql.Data.MySqlClient.MySqlCommand(myQuery)
dr = myCommand.ExecuteReader
bite = DirectCast(dr("Photo"), Byte())
Catch ex As MySql.Data.MySqlClient.MySqlException
InsertError = True
End Try
Try
MyADOConnection.Close()
Catch exclose As MySql.Data.MySqlClient.MySqlException
CloseError = True
End Try
If InsertError Then
FunctionErrorState = True
End If
Return bite 'I just put something random here since I don't know what to retun
End Function
It looks to me like the image is being stored as a byte array in the database. You (i guess correctly) read this array from the database with the command bite = DirectCast(dr("Photo"), Byte()) in your ShowPic function. A byte array is just a large blob of data in memory, that you later query with the MemoryStream.
Therefore your ShowPic function (which is more a GetPic function ;-) should return Byte()
Public Function Showpic(ByVal user As String) As Byte()
You should initialize bite with Nothing
Dim bite As Byte() = Nothing
That way if an error occurs, the array will be nothing and you can check for that.
In order to convert the byte array, that contains the raw image data into an image you correctly use a MemoryStream and the Image.FromStream method. I/O in .NET works in large portions with streams. They are just a way to continously feed data from some source. In this case the source is just the memory, in particular the Byte array you got from the database.
You however never use that Byte array. Assign the result of the ShowPic function to a variable, in order to use it:
Public Sub ShowPicture(ByVal username As String)
user = username
Dim ImageData As Byte() = ModuleQuery.Showpic(username)
If ImageData IsNot Nothing Then
Using ms As New MemoryStream(ImageData)
prof_pic.Image = Image.FromStream(ms)
End Using
Else
'Your function returned nothing, so an error occured.
'This is a very crude way of error handling, since you never
'see the error in the first place, which makes debugging a
'nightmare. There are better ways, out of scope of this answer.
MessageBox.Show("No image retrieved due to an error :(")
End If
End Sub
That way you retrieve the image data from the database (again, rename it to GetPic or GetImageData or something) in ShowPic and return its raw data to the ShowPicture method where you decode and show it.

MySqlDataReader not returning data

As part of a project to import data into wordpress via screen scraping I've a database table of old and new URL's stored in a MySQL database. In the example below the ExecuteReader command doesn't appear to be returning any data (-1 rows effected), I've ran the SQL via workbench and that returns data, so it's not the SQL or data in the database.
At other times within the code I've called ExecuteNonQuery() and ExecuteScalar() both without issue (so it isn't the connection string).
Any ideas what to try next?
Dim SQL As String
Dim conn As MySqlConnection = New MySqlConnection(_CONNECTIONSTRING)
SQL = "SELECT OrgURL, NewURL FROM `wp_user`.`tbl_linkdata`"
Try
conn.Open()
Dim cmd As MySqlCommand = New MySqlCommand(SQL, conn)
Dim dr As MySqlDataReader = cmd.ExecuteReader()
While (dr.Read)
LinkHashMap.Add(dr.GetString(0), dr.GetString(1))
End While
Console.ForegroundColor = ConsoleColor.Cyan
Console.WriteLine("The Hash map contains " + dr.RecordsAffected + " rows")
dr.Close()
Catch ex As Exception
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine("Exception loading the hashtable : " + ex.Message)
Finally
conn.Dispose()
End Try
DataReader.RecordsAffected always returns -1 for a SELECT command. What does LinkHashMap.Count return? In MySqlDataReader it is the same:
"The number of rows changed, inserted, or deleted. -1 for SELECT
statements"
If you want to count the number of records you can use LinkHashMap.Count.
You: "LinkHashMap is "Nothing" "
How do you want to add something to it without initializing it first? A NullReferenceException should have happened. So initialize the dictionary (or whatever it is) first via constructor:
Dim LinkHashMap As New Dictionary(Of String, String)
While (dr.Read)
LinkHashMap.Add(dr.GetString(0), dr.GetString(1))
End While

VB.net data retrieval and display

So, for some reason I can't work out I think the below is only retrieving the 1st letter of the value within the column I'm trying to search. (Note: the database is called m1 and contains 11 columns in total).
I tested the query first in SQL Admin and it worked properly (I think).
I then wrote this myself using documentation, I think I've more that likely made a mistake somewhere..
Dim hostnameQuery As String = "SELECT `HOSTNAME` FROM `m1` WHERE 1"
Dim SQLConnection As New MySqlConnection(My.Settings.connStr)
Dim cmd As New MySqlCommand(hostnameQuery, SQLConnection)
Try
SQLConnection.Open()
cmd.ExecuteNonQuery()
Dim reader As MySqlDataReader
reader = cmd.ExecuteReader
While reader.Read
main.Label64.Text = (reader.GetChar(0))
End While
Catch ex As Exception
MsgBox(ex.Message.ToString)
Finally
SQLConnection.Close()
End Try
I added this to a button click so when I click the button only the letter 'M' appears but the value is 'M1'
What have I done wrong?
That's because you requested only a character. Try using GetString() instead of GetChar() :
main.Label64.Text = (reader.GetString(0))
There are many things that can be improved in your code.
First of all, you can remove the condition WHERE 1, because it means "EVERYTHING" so it is not useful.
Secondly, you can avoid calling cmd.ExecuteNonQuery() because it is usually used to run an instruction that does not return anything (like INSERT).
Finally, if you are interested only to the first returned row, you can avoid the While loop and use cmd.ExecuteScalar() instead.
To summarize, instead of:
cmd.ExecuteNonQuery()
Dim reader As MySqlDataReader
reader = cmd.ExecuteReader
While reader.Read
main.Label64.Text = (reader.GetChar(0))
End While
simply do this:
main.Label64.Text = Convert.ToString(cmd.ExecuteScalar())