vb net set timeout period in connection string mysql - mysql

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

Related

Can't open a connection to create a transaction

In MS-Access, I'm trying to get a connection so that I can run queries within a transaction.
Stripped down, the routine looks like this:
Public Sub SetConnection()
Dim ConnectionString As String
ConnectionString = CurrentDb.TableDefs("RandomTable").Connect
If conn Is Nothing Then
Set conn = New ADODB.Connection
PostToLog "SetConnection()", "Set Connection to " & ConnectionString
conn.Open ConnectionString ' Fails here
' conn.Open ' Gives the same error without specifying the connection
End If
Exit Sub
I can see that the connection string is exactly that set in the Linked Table Manager.
Then I use it like this
Public Sub Begin()
PostToLog "Begin()", "Start Begin"
SetConnection
If Not (conn Is Nothing) Then
PostToLog "Begin()", "Begin"
conn.BeginTrans
End If
End Sub
Public Sub Commit()
PostToLog "Commit()", "Start Commit"
If Not (conn Is Nothing) Then
PostToLog "Commit()", "Committing"
conn.CommitTrans
End If
CloseConnection
End Sub
Public Function GetConnection() As ADODB.Connection
' Use GetConnection() everywhere you want a connection. If in a transaction, these queries will automatically be included.
' The exception would be items that you do NOT want rolled back in case of failure, like logging.
If conn Is Nothing Then
' Set GetConnection = New ADODB.Connection
Set GetConnection = CurrentProject.Connection
Else
Set GetConnection = conn
End If
End Function
But the connection fails to open, conn isn't set, and everything happens outside a transaction.
The error is
Unspecified error [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified: ConnectionString: ODBC;DSN=....
I've also tried
ConnectionString = CurrentProject.Connection.ConnectionString
but that looked like the connection string to the front end Access database, not the back end.
I can't find any excuse for why the linked tables can find the DSN, but can't when I create the connection.
Begin, Commit, Rollback are used like so....
objSQL.Begin ' Start transaction
' do some stuff that uses the conn connection
objSQL.Commit
Err:
objSQL.Rollback
Update:
Using conn = CurrentProject.Connection instead of creating a new ADODB connection appears to work. No errors are thrown.
But the changes do not appear, as if they all get rolled back.
Postgres doesn't allow for a dirty read, so I can't tell if the changes never happened or if they do and get reversed. And if they do get reversed, I can't tell if that is before or after the Commit or what exactly triggers it. I can see the SQL statements appearing to get executed on the Postgres connection.
I'm going to try exploring a little more what happens when I have a proper connection string, as demonstrated by #HansUp

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.

an error keeping popping up in my codes (connection already open)

This error keeps popping up!!! An unhandled exception of type 'System.InvalidOperationException' occurred in MySql.Data.dll
Additional information: The connection is already open.
Dim cmd As MySqlCommand
con.Open()
Try
cmd = con.CreateCommand()
cmd.CommandText = "update animal_sale set #NOAB,#Amount,#Tax,#Total where Species=#Species"
cmd.Parameters.AddWithValue("#Species", TextBoxSpecies.Text)
cmd.Parameters.AddWithValue("#NOAB", TextBoxNo.Text)
cmd.Parameters.AddWithValue("#Amount", TextBoxAmount.Text)
cmd.Parameters.AddWithValue("#Tax", TextBoxTax.Text)
cmd.Parameters.AddWithValue("#Total", TextBoxTotal.Text)
cmd.ExecuteNonQuery()
load()
Catch ex As Exception
End Try
End Sub
It looks like you are not closing the connection after executing the query. You only have
con.Open()
and are not closing the connection after
cmd.ExecuteNonQuery()
Keep your database objects local to the method where they are used. Then you always know the state of a connection and can be sure they are closed and disposed. Using...End Using blocks do this for you even if there is an error. In this code both the connection and the command are covered by a single Using block. Note the comma at the end of the first Using line.
You can pass your connection string directly to the constructor of the connection.
You can pass your command text and the connection directly to the constructor of the command.
You Update sql command is not correct. You need to tell the server what fields to update. I had to guess at the names of the fields. Check you database for the correct names and adjust the code accordingly.
Please don't use .AddWithValue. See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
Here is another
https://andrevdm.blogspot.com/2010/12/parameterised-queriesdont-use.html
I had to guess at the datatypes and field size for the .Add method. Check you database for the correct values and adjust the code.
I converted the text box strings to the proper datatype here in the database code but normally these values would be parsed and converted before they reach this code.
Private Sub UpdateSale()
Using con As New MySqlConnection("Your connection string"),
cmd As New MySqlCommand("update animal_sale set nonab = #NOAB, amount = #Amount, tax = #Tax, total = #Total where species = #Species;", con)
cmd.Parameters.Add("#Species", MySqlDbType.VarChar, 100).Value = TextBoxSpecies.Text
cmd.Parameters.Add("#NOAB", MySqlDbType.Int32).Value = CInt(TextBoxNo.Text)
cmd.Parameters.Add("#Amount", MySqlDbType.Decimal).Value = CDec(TextBoxAmount.Text)
cmd.Parameters.Add("#Tax", MySqlDbType.Decimal).Value = CDec(TextBoxTax.Text)
cmd.Parameters.Add("#Total", MySqlDbType.Decimal).Value = CDec(TextBoxTotal.Text)
con.Open
cmd.ExecuteNonQuery()
End Using
End Sub

How to make a vb application work with a SQL database from any computer?

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

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.