Show image using function - mysql

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.

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.

how to save a byte() to my SQLDatabase using VB.net

I know that there are already a couple of questions which seems like my problem but I tried to copy a lot of it and tried but can’t get the resold I want.
Actually is my target to save an image from a Picture Box as Byte() into mySQL Database.
At first I tried the simple way like
Dim acCust As Image = pgbox.image
Dim picBytes() As Byte
Using ms As New MemoryStream
cust.Save(ms, cust.RawFormat)
picBytes = ms.ToArray()
End Using
but with this I run into a general GUI error so I copied the Picture at first like this
Dim rec As New Rectangle(0, 0, acCust.Width, acCust.Height)
Dim mus As New ImageFormatConverter
Dim muster As New Bitmap(rec.Width, rec.Height)
Dim cust As Image
Using grp = Graphics.FromImage(muster)
grp.DrawImage(acCust, New Rectangle(0, 0, rec.Width, rec.Height), rec, GraphicsUnit.Pixel)
cust = muster
End Using
If I use after that again the code
Dim picBytes() As Byte
Using ms As New MemoryStream
cust.Save(ms, cust.RawFormat)
picBytes = ms.ToArray()
End Using
sqlconection.Open()
Dim query As String = "INSERT INTO tblimg(img) VALUES ('#image');"
Dim com As New MySqlCommand(query, sqlconection)
com.Parameters.AddWithValue("image", picBytes)
com.ExecuteNonQuery()
sqlconection.Close()
everything looks sofa ok but if I read it like this
Dim imgData As Byte()
Dim sql As String = "SELECT img FROM tblimg"
sqlconection.Open()
Dim cmd As New MySqlCommand(sql, sqlconection)
Using rdr As MySqlDataReader = cmd.ExecuteReader
If rdr.HasRows Then
rdr.Read()
imgData = TryCast(rdr.Item("img"), Byte())
' in case this record has no image
If imgData IsNot Nothing Then
' ToDo: dispose of any previous Image
' create memstream from bytes
Using ms As New MemoryStream(imgData)
' create image from stream, assign to PicBox
pbbox.Image = CType(Image.FromStream(ms), Image)
End Using
End If
End If
End Using
I got an alarm message
Eine nicht behandelte Ausnahme des Typs "System.ArgumentException" ist in System.Drawing.dll aufgetreten.
Zusätzliche Informationen: Ungültiger Parameter.
(Sorry it's in German)
Has anybody an idea what and were it’s going wrong?
If I use the the picByts () in a new memory stream and convert it back to an image then I got the correct result. It seems like there is a problem with the up or download query
in my Server I use the variable type LongBlob
You save a Byte array to a database in exactly the same way as you save any other data. You write your SQL, you add a parameter to a command and you set its value. This:
Dim query As String = "INSERT INTO tblimg(img) VALUES ('#image');"
Dim com As New MySqlCommand(query, sqlconection)
com.Parameters.AddWithValue("image", picBytes)
is wrong. You only wrap literal strings in single quotes in SQL code. That should be like this:
Dim query As String = "INSERT INTO tblimg(img) VALUES (#image);"
Dim com As New MySqlCommand(query, sqlconection)
com.Parameters.AddWithValue("#image", picBytes)
No single quotes around the parameter in the SQL and use the actual parameter name when adding it to the command. I'd also recommend using Add rather than AddWithValue but that's a discussion for another time.

Parameterize SQL Queries

I want parameterize some SQL Statements so my code isn't vunerable to SQL Injections any longer But i have actually no plan how to parameterize for example a where clause.
Dim accID As String = DatabaseConnecter.readField("SELECT ID FROM accounts WHERE accountname ='" & user & "' AND password='" & pw & "';")
The Problem is if you type in a given username, for example test and extend the username with. You can log in without entering the password into the Application.
Edit:
Public Function readField(ByVal sql As String) As String
Dim output As String = "ERROR"
Using cn = New MySqlConnection(connString.ToString())
Using cmd = New MySqlCommand(sql, cn)
cn.Open()
Using rd = cmd.ExecuteReader()
Try
rd.Read()
output = rd.GetString(0)
rd.Close()
Catch ex As Exception
End Try
End Using
cn.Close()
End Using
End Using
Return output
End Function
´´´
To have a parameterized query you need to create parameters and write a proper SQL text where, in place of values typed directly from your user, you have parameter placeholders.
So, for example, you sql text should be something like this
Dim sqlText = "SELECT ID FROM accounts WHERE accountname =#name AND password=#pwd"
Now you have a parameterized text, but stil we need to create the parameters that will be sent to the database engine together with your sql command.
You can create the parameter (two in this case) in this way before calling the method that executes the query
Dim p1 as MySqlParameter = new MySqlParameter("#name", MySqlDbType.VarChar)
p1.Value = user
Dim p2 as MySqlParameter = new MySqlParameter("#pwd", MySqlDbType.VarChar)
p2.Value = password
Dim pms As List(Of MySqlParameter) = new List(Of MySqlParameter)()
pms.Add(p1)
pms.Add(p2)
Now we need to pass this list to your method (and this requires changes to your method signature)
DatabaseConnecter.readField(sqlText, pms)
The method itself should change to something like
Public Function readField(ByVal sql As String, Optional pms As List(Of MySqlParameter) = Nothing) As String
Dim output As String = "ERROR"
Using cn = New MySqlConnection(connString.ToString())
Using cmd = New MySqlCommand(sql, cn)
cn.Open()
' This block adds the parameter defined by the caller to the command
' The parameters are optional so we need to check if we have really received the list or not
if pms IsNot Nothing Then
cmd.Parameters.AddRange(pms.ToArray())
End If
Using rd = cmd.ExecuteReader()
Try
rd.Read()
output = rd.GetString(0)
rd.Close()
Catch ex As Exception
End Try
End Using
' no need to close when inside a using block
' cn.Close()
End Using
End Using
Return output
End Function
The method now has an optional parameter that will contain the list of the parameters required by the query (or nothing if your query doesn't require parameters). This list is added to the command parameters collection and the query is now executed.
Final Note: Storing passwords in clear text into a database is a well known security problem. I suggest you to search about how to store passwords in a database.
Private Function GetID(User As String, pw As String) As String
Using cmd As New SqlCommand("SELECT ID FROM accounts WHERE accountname =#user AND password=#password", New SqlConnection(SQLConnString))
cmd.Parameters.AddWithValue("#user", User)
cmd.Parameters.Add("#password", SqlDbType.NVarChar)
cmd.Parameters("#password").Value = pw
Try
cmd.Connection.Open()
Return cmd.ExecuteScalar()
Catch ex As Exception
'handle error
Return Nothing
Finally
cmd.Connection.Close()
End Try
End Using
End Function
I've demostrated two methods of setting the parameters. Search for more info or comparison.

Uploading images to database using the BLOB throwing exception

I've been attempting to adapt part of this procedure that I found online (can't remember where now!). I've been trying to use this to upload images to a MYSQL database using BLOB data type.
Public Sub SQLUpload()
Dim connection As New MySqlConnection(ConnectionImage)
Dim command As New MySqlCommand("INSERT INTO Images (File, FileName, FileSize) VALUES (#Picture, 'Name1', 'Size1')", connection)
'Create an Image object.'
Using picture As Image = Image.FromFile("C:\DIR\Pictures\Person.jpg")
'Create an empty stream in memory.'
Using stream As New IO.MemoryStream
'Fill the stream with the binary data from the Image.'
picture.Save(Stream, Imaging.ImageFormat.Jpeg)
'Get an array of Bytes from the stream and assign to the parameter.'
command.Parameters.AddWithValue("#Picture", SqlDbType.VarBinary).Value = stream.GetBuffer()
End Using
End Using
connection.Open()
Try
command.ExecuteNonQuery()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
connection.Close()
End Sub
Above is the current sub routine. Whenever this is executed, the routine operates fine until it gets to:
Command.ExecuteNonQuery()
It throws the error:
Unable to cast object of type System.Byte[] to type System.IConvertible
I'm pretty sure this happens because of the fact that the bytes from the image are returned as an array however the memory that they are saved to does not support an array? This was just gathered from reading I've done elsewhere online.
However, as this is not all my code I am frankly not sure what the problem is. Can anyone see what is wrong with it?
Many Thanks
Where you have
SqlDbType.VarBinary ' <-- this is Sql Server DB type
use
MySqlDbType.Blob
Like this
Dim file() As Byte = ' set your file
Dim p As MySqlParameter = new MySqlParameter("#Picture", MySqlDbType.Blob, file.Length)
p.Value = file
command.Parameters.Add(p)
As it mentioned by others, you don't need to "Save" your file - just read it into byte array. My code would look something like below:
Public Sub SQLUpload()
Try
Using conn As New MySqlConnection(connString)
' Parametarize entire sql string
Dim sql As String =
"INSERT INTO Images (File, FileName, FileSize) VALUES (#Picture, #name, #size)"
Using cmd As New MySqlCommand(sql, conn)
Dim fileName As String = "C:\DIR\Pictures\Person.jpg"
Dim file() As Byte = File.ReadAllBytes(fileName)
cmd.Parameters.AddWithValue("#Picture", MySqlDbType.Blob).Value = file
cmd.Parameters.AddWithValue("#file", MySqlDbType.VarChar).Value = fileName
cmd.Parameters.AddWithValue("#size", MySqlDbType.Int32).Value = file.Length
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
MessageBox.Show("Success")
Catch ex As Exception
MessageBox.Show(ex.ToString())
End Try
End Sub

vb net SQl query problem

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.