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.
Related
I'm trying to join tables and load data with a specific value from a Textbox but It's giving the following error:
"An exception of type 'System.NullReferenceException' occurred in Boxing.exe but was not handled in user code
Additional information: Object reference not set to an instance of an object."
My code:
Dim Joinloin As New MySqlCommand("SELECT boxno, specie, netweight, producttype, loin FROM loins, boxing WHERE loins.code = boxing.loin AND type = '" & Label9.text & "' ORDER BY loincode", conn.getConnection)
I tried to run without the "type = '" & Label9.text & "'" and works perfectly.
Because "Type" is a reserved word in SQL, you need to change it in your SQL Database and in your Query to something like "TypeX" and try again.
Connections and Commands need to have their Dispose methods called so they can release unmanaged resources. To do this they should be declared in the method they are are used. Using...End Using blocks handle the declare, and Close/Dispose.
Don not concatenate strings to build sq statements. Always use parameters.
Your join syntax went out with the last milenium. I made wild guesse about which field belonged to which table. Is there really a field called loincode?
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dt = GetProductData(Label9.Text)
'Do something with the data table
End Sub
Private Function GetProductData(type As String) As DataTable
Dim dt As New DataTable
Using cn As New MySqlConnection("You connection string"),
cmd As New MySqlCommand("SELECT boxing.boxno, loins.specie, boxing.netweight, loins.producttype, boxing.loin
FROM boxing
JOIN loins ON boxing.loin = loins.code Where loins.[type] = #Type
ORDER BY boxing.loincode", cn)
cmd.Parameters.AddWithValue("#Type", type)
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
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.
Most of my programming experience is c-based, so I don't have the clearest understanding of how SQL (specifically, the mySQL platform) works.
My vb.net application works completely fine on the computer I made it on. However, if I download it onto another computer, the mySQL connection fails to open. From what I've read on other StackOverflow posts, that's the fault of the connection string. My connection string looks something like this:
"server=xxx.xxx.xxx.xxx;uid=username;pwd=password;database=db;default command timeout=300"
Again, for the base computer, this works fine without any problems at all. It's when I run the program from a different computer when I run into trouble. Do I need to change the server number? I've tried doing that, but the program still doesn't work. Is there one more field I need to add into the string? Or do I need to configure mySQL settings in some way on each computer? I would like to change the program in a way that allows anybody to use it immediately upon download. Would any of the methods listed above work, or a completely different one entirely?
Thanks.
This is a simple class I use with MySQL. Replace everything in [bracket] by your values. if It's not working look at your firewall and also use MySQL WorkBench to create user/password/permission/schema. Make sure you can connect to your database with MySQL workbench then you know you have everything setup right.
Imports MySql.Data.MySqlClient
Public Class mysql
'Connection string for mysql
Public SQLSource As String = "Server=[x.x.x.x];userid=[yourusername];password=[yourpassword];database=[defaultdatabaseifany];"
'database connection classes
Private DBcon As New MySqlConnection
Private SQLcmd As MySqlCommand
Public DBDA As New MySqlDataAdapter
Public DBDT As New DataTable
' parameters
Public Params As New List(Of MySqlParameter)
' some stats
Public RecordCount As Integer
Public Exception As String
Function ExecScalar(SQLQuery As String) As Long
Dim theID As Long
DBcon.ConnectionString = SQLSource
Try
DBcon.Open()
SQLcmd = New MySqlCommand(SQLQuery, DBcon)
'loads params into the query
Params.ForEach(Sub(p) SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value))
'or like this is also good
'For Each p As MySqlParameter In Params
' SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value)
' Next
' clears params
Params.Clear()
'return the Id of the last insert or result of other query
theID = Convert.ToInt32(SQLcmd.ExecuteScalar())
DBcon.Close()
Catch ex As MySqlException
Exception = ex.Message
theID = -1
Finally
DBcon.Dispose()
End Try
Return theID
End Function
Sub ExecQuery(SQLQuery As String)
DBcon.ConnectionString = SQLSource
Try
DBcon.Open()
SQLcmd = New MySqlCommand(SQLQuery, DBcon)
'loads params into the query
Params.ForEach(Sub(p) SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value))
'or like this is also good
'For Each p As MySqlParameter In Params
' SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value)
' Next
' clears params
Params.Clear()
DBDA.SelectCommand = SQLcmd
DBDA.Update(DBDT)
DBDA.Fill(DBDT)
DBcon.Close()
Catch ex As MySqlException
Exception = ex.Message
Finally
DBcon.Dispose()
End Try
End Sub
' add parameters to the list
Public Sub AddParam(Name As String, Value As Object)
Dim NewParam As New MySqlParameter(Name, Value)
Params.Add(NewParam)
End Sub
End Class
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.
i have a program that proccess a huge database, it's around 4,8k records.. i'm populating the data into two 2d array, comparing it, then insert the result into database in form of new table..
and i also have two set of database, the smaller one with only 40 records and the biggest one with 4,8k records.. when i tested the smaller database, program runs correctly
but when i'm using the biggest one, the error occured.
i've already try to identified the connection leak, but it turned out that there isn't any.
i've already closed all the connection properly with dispose or close
but the first error message was the infamous ** timeout period period. . . max pool size was reached**
later after i dismiss the error message, another error message popped out the connection must be valid and open though i've already re-checked that problem
i'm using vs 2005 and i search to google that this error was the bug that occured in vs 2005, but i couldn't never properly find the solution that microsoft provided
so i'm thinking is there a way to fix this, like modified the connection function. what should i change in my code below?
Imports MySql.Data.MySqlClient
Public Class koneksi
Private Conn As MySqlConnection = Nothing
Public Function konek() As MySqlConnection
Dim ConnString As String
ConnString = ";server=localhost;user=root;password=;database=skripsi2;"
Try
Conn = New MySqlConnection(ConnString)
Conn.Open()
Catch ex As Exception
MessageBox.Show("Koneksi Error " + ex.Message)
End Try
Return Conn
End Function
End Class
*note: what i've already done yet is set the connection timeout to 0/300. set the pooling to true and give the max pool size = 200
but all that attempt was in vain.. nothing worked..
so could you please tell me how to fix this? i 've worked my brains out over one week and still got no solution for this
i'm using vb.net 2005 and mysql as database
'UPDATE CODE EXAMPLE CALLING THE CONNECTION FUNCTION
Dim resnode1 As String = "..."
CMD_resnode = New MySqlCommand(resnode1, conn.konek)
resnode = CMD_resnode.ExecuteReader()
Dim getmaxrow2 As String = "..."
CMD_maxrow2 = New MySqlCommand(getmaxrow2, conn.konek)
maxrow2 = Convert.ToInt32(CMD_maxrow2.ExecuteScalar())
CMD_maxrow2.Connection.Dispose()
maxrow22 = maxrow2 - 1
IF....THEN
....
resnode.read()
....
END IF
CMD_resnode.connection.dispose()
From my experience the timeout error is hardly about the connection. It rather has to do with the command the data adapter creates before it executes. If you're creating a data adapter by passing a sql query in a String then the adapter will create its own command. You have to get that command object from the SelectCommand property of the adapter and set its CommandTimeout.
Try:
mydataAdaptor.SelectCommand.CommandTimeout = xxxx
xxxx being some long time interval such as 60000 (1 hour)
As per the this stack-overflow thread . Its good practice to use close() method.
Dim resnode1 As String = "..."
CMD_resnode = New MySqlCommand(resnode1, conn.konek)
resnode = CMD_resnode.ExecuteReader()
Dim getmaxrow2 As String = "..."
CMD_maxrow2 = New MySqlCommand(getmaxrow2, conn.konek)
maxrow2 = Convert.ToInt32(CMD_maxrow2.ExecuteScalar())
CMD_maxrow2.Connection.Close()
maxrow22 = maxrow2 - 1
IF....THEN
....
resnode.read()
....
END IF
CMD_resnode.connection.Close()
If still facing the problem, try running SQL Queries on command line and check the execution time of your query.
It is difficult to diagnose this kind of problems, however, I can see in your example code the usual pattern with connections beeing created and leaked because they are not properly closed and returned to the connection pool. Your code force the creation of a new connection every time you call conn.konek and you seems to forget to close and dispose the instance created in the call.
Until the pool is exausted and you receive the fatal error.
A simple approach is to check your code where you call the conn.konek method and change it to something like this
' Just one call to konek and keep the instance for using in the enclosed block '
Using con = conn.konek
Dim resnode1 As String = "..."
CMD_resnode = New MySqlCommand(resnode1, con)
resnode = CMD_resnode.ExecuteReader()
....
Dim getmaxrow2 As String = "..."
CMD_maxrow2 = New MySqlCommand(getmaxrow2, con)
maxrow2 = Convert.ToInt32(CMD_maxrow2.ExecuteScalar())
maxrow22 = maxrow2 - 1
' Here the connection is closed and disposed.
End Using
In this way you create only one connection and encapsulate it in a Using Statement, at the End Using point the connection is automatically closed and disposed ALSO IF THE block of code internal at the using block raises an exception.
If you need to keep the DataReader open while you execute other commands then you could try
' Just one call to konek and keep the instance for using in the enclosed block '
Using con = conn.konek
Dim resnode1 As String = "..."
CMD_resnode = New MySqlCommand(resnode1, con)
resnode = CMD_resnode.ExecuteReader()
....
Using con1 = conn.konek
Dim getmaxrow2 As String = "..."
CMD_maxrow2 = New MySqlCommand(getmaxrow2, con1)
maxrow2 = Convert.ToInt32(CMD_maxrow2.ExecuteScalar())
maxrow22 = maxrow2 - 1
' Here the connection for the command is closed and disposed.
End Using
' Here the connection for the datareader is closed and disposed.
End Using