VB.Net reuse sql connection - mysql

I'm a newbie to vb.net, I'd like to ask is there a way to reuse the sql connection command?
Here is the code for my main.vb:
Dim ServerString As String = "Server=localhost;User Id=root;Password=;Database=pos"
Dim SQLConnection As MySqlConnection = New MySqlConnection
Private Sub Main_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
SQLConnection.ConnectionString = ServerString
Try
If SQLConnection.State = ConnectionState.Closed Then
SQLConnection.Open()
Else
SQLConnection.Close()
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
Since I'd like to use this in my other classes, i don't want to re-write this code in every form. Any help is truly appreciated. Thanks.

Reusing a connection (or any other unmanaged resource) is normally not a good idea. You should dispose them as soon as possible.
But there's no problem in always creating a new connection anyway, since you're using the ADO.NET connection-pool by default. So you are not creating (and opening) a new physical connection. Actually you're just telling the pool that a conenction is reusable somewhere else now when you close/dispose it. And when you open it, it cannot be used somewhere else, that's why it's important to always close it.
Therefore always use the Using-statement.
Public Shared Function GetColumn1(column2 As Int32) As String
Dim sql = "SELECT Column1 From dbo.tableName WHERE Column2=#Column2 ORDER BY Column1 ASC"
Using con = New SqlConnection(connectionString)
Using cmd = New SqlCommand(sql, con)
cmd.Parameters.AddWithValue("#Column2", column2)
Try
con.Open()
Using rd = cmd.ExecuteReader()
If rd.Read() Then
Dim Column1 As String = rd.GetString(0)
Return Column1
Else
Return Nothing
End If
End Using
Catch ex As Exception
' log the exception here or do not catch it '
' note that you don't need a Finally to close the connection '
' since a Using-Statement disposes the object even in case of exception(which also closes a connection implicitely)
End Try
End Using
End Using
End Function
Above is a sample method to demontrate that you should not reuse anything.

This is what I normally do: I create a class, e.g. ConnectDB, and a method within this class, e.g. GetConnection. Here is the code:
Imports System.Data
Imports System.Data.SqlClient
Public Class ConnectDB
Public Shared Function GetConnection() As SqlConnection
Dim dbConnString As String = "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True"
Return New SqlConnection(dbConnString)
End Function
End Class
Then from the method that needs a connection to the database, I call this function. Here is a sample code:
Imports System.Data.SqlClient
Public Class EmployeeDB
Public Shared Function GetEmployees() As List(Of Employee)
Dim con As SqlConnection = ConnectDB.GetConnection()
Dim selectStmt As String = "SELECT * FROM Employees"
Dim selectCmd As New SqlCommand(selectStmt, con)
Dim employees As New List(Of Employee)
Try
con.Open()
Dim reader As SqlDataReader = selectCmd.ExecuteReader()
Do While reader.Read
Dim employee as New Employee
employee.LastName = reader("LastName").ToString
employee.FirstName = reader("FirstName").ToString
...
employees.Add(employee)
Loop
reader.Close()
Catch ex As Exception
Throw ex
Finally
con.Close()
End Try
Return employees
End Function
End Class
You can also modify the selectStmt string to include filter conditions, parameters, and sort order just like Tim's example above and include selectCmd.Parameters.AddWithValue("#<parameterName>", value) for each of your parameters.

Related

My code was working earlier until I added error messages for checking if CapNum is empty or already existed on the database

Dim cmd As MySqlCommand
cmd = con.CreateCommand
con.Open()
Try
If String.IsNullOrEmpty(capNum.Text.ToString()) Then
MessageBox.Show("Please fill up the Capstone Number to proceed.")
Else
Dim theQuery As String = "select * from listofcapstone where caps_Number like '%" & capNum.Text & "%'"
Dim cmd1 As MySqlCommand = New MySqlCommand(theQuery, con)
Dim reader As MySqlDataReader = cmd1.ExecuteReader()
If reader.HasRows Then
reader.Close()
MessageBox.Show("There's already an existing data with this Capstone Number!")
Else
cmd.CommandText = "insert into listofcapstone(caps_Number, thesis_Title, ictdu_entNumber, year, course)values(#caps_Number, #thesis_Title, #ictdu_entNumber, #year, #course)"
cmd.Parameters.AddWithValue("#caps_Number", capNum.Text)
cmd.Parameters.AddWithValue("#thesis_Title", title.Text)
cmd.Parameters.AddWithValue("#ictdu_entNumber", ictduCapNum.Text)
cmd.Parameters.AddWithValue("#year", yr.Text)
cmd.Parameters.AddWithValue("#course", course.Text)
cmd.ExecuteNonQuery()
MessageBox.Show("SUCCESSFULLY ADDED!")
capNum.Clear()
title.Clear()
ictduCapNum.Clear()
course.Clear()
yr.SelectedIndex = -1
End If
End If
Catch ex As Exception
MessageBox.Show("Connection Lost!!")
Me.Close()
End Try
con.Close()
I found the problem on my code..i tried to remove try and catch to see which part of the code wasnt used properly and receive the "MySqlException was unhandled" error message..then put a reader on the else part
Dim theQuery As String = "select * from listofcapstone where caps_Number like '%" & capNum.Text & "%'"
Dim cmd1 As MySqlCommand = New MySqlCommand(theQuery, con)
Dim reader As MySqlDataReader = cmd1.ExecuteReader()
If reader.HasRows Then
reader.Close()
MessageBox.Show("There's already an existing data with this Capstone Number!")
Else
reader.Close() 'Where I put the reader.'
cmd.CommandText = "insert into listofcapstone(caps_Number, thesis_Title, ictdu_entNumber, year, course)values(#caps_Number, #thesis_Title, #ictdu_entNumber, #year, #course)"
cmd.Parameters.AddWithValue("#caps_Number", capNum.Text)
cmd.Parameters.AddWithValue("#thesis_Title", title.Text)
I suggest you use parameterized queries instead of concatenating your queries like you're doing with that SELECT statement in order to mitigate SQL Injection attacks. You can read this and this to learn more about it.
You can also use the Using statement that will dispose of any object that has implemented the IDisposable interface such as the MySqlConnection and MySqlCommand objects. From the documentation:
Sometimes your code requires an unmanaged resource, such as a file
handle, a COM wrapper, or a SQL connection. A Using block guarantees
the disposal of one or more such resources when your code is finished
with them. This makes them available for other code to use.
You can also break down into separate Sub routines the queries for retrieving a record and inserting a new one. I put together a basic example showing what I discussed:
Imports System
Imports System.Data
Imports MySql.Data
Imports MySql.Data.MySqlClient
Namespace MySqlCmdExample
Class Program
Private Shared Sub Main(args As String())
Dim dataProvider As New AlbumDataProvider()
Try
If dataProvider.AlbumExists("Album_Five") Then
Console.WriteLine("Album exists...")
Return
End If
Console.WriteLine("Adding new album...")
dataProvider.AddAlbum(3, "Album_Five")
Catch ex As MySqlException
Console.WriteLine([String].Format("Oops, an error occurred: {0}", ex.Message))
End Try
End Sub
End Class
Public Class AlbumDataProvider
Private connectionString As String = "server=localhost;user=<your_username>;database=stack_overflow;port=3306;password=<your_password>"
Public Sub New()
End Sub
Public Function AlbumExists(name As String) As Boolean
Dim found As Boolean = False
Using conn As New MySqlConnection(connectionString)
If conn.State = ConnectionState.Closed Then
conn.Open()
End If
Dim cmd As New MySqlCommand("SELECT * FROM Album WHERE `Name` = #albumName", conn)
cmd.Parameters.AddWithValue("#albumName", name)
Using reader As MySqlDataReader = cmd.ExecuteReader()
found = reader.HasRows
End Using
End Using
Return found
End Function
Public Sub AddAlbum(ownerId As Integer, name As String)
Using conn As New MySqlConnection(connectionString)
If conn.State = ConnectionState.Closed Then
conn.Open()
End If
Dim cmd As New MySqlCommand("INSERT INTO Album(OwnerId, Name) VALUES(#ownerId, #albumName)", conn)
cmd.Parameters.AddWithValue("#ownerId", ownerId)
cmd.Parameters.AddWithValue("#albumName", name)
cmd.ExecuteNonQuery()
End Using
End Sub
End Class
End Namespace

VB.NET function return error and exit sub

I have this connection function in my VB.NET project
Public Function OpenMysqlCon() As MySqlConnection
Dim mMysqlconnection = New MySqlConnection()
Try
Dim strconDB As String = "server='192.168.100.2'; database='mydb';Port=3306; UID='epb'; password='hahaha'; pooling=true"
mMysqlconnection = New MySqlConnection
mMysqlconnection.ConnectionString = strconDB
mMysqlconnection.Open()
OpenMysqlCon = mMysqlconnection
Catch exceptionThatICaught As System.Exception
OpenMysqlCon = Nothing
End Try
End Function
And i will call the function in my VB project something like
Private Sub frmTest_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Using Con=OpenMysqlCon()
'mycode here
End Using
End Sub
However when the connection is not available, it will throw an exception.
How can i avoid the exception by giving a msgbox something like connection not available at the moment, please try again later and then exit the sub that was using the function?
End Sub
The best approach is to not hold the connection in a field of the form but to create and initalize it wherever you need it. The connection-pooling will ensure that no physical connection needs to be created.
So don't use a OpenMysqlCon method at all but code like this(GetAllUsers is just an example):
Public Function GetAllUsers() As List(Of User)
Dim userList = New List(Of User)
Try
Using mMysqlconnection = New MySqlConnection("server='192.168.100.2'; database='mydb';Port=3306; UID='epb'; password='hahaha'; pooling=true")
mMysqlconnection.Open()
Using command = New MySqlCommand("SELECT * FROM USER ORDER By UserName", mMysqlconnection)
Using rdr = command.ExecuteReader()
While rdr.Read()
Dim user = New User()
user.UserName = rdr.GetString(0)
userList.Add(user)
End While
End Using
End Using
End Using
Catch exceptionThatICaught As System.Exception
MessageBox.Show("meaningful message here, logging would be useful too")
Return Nothing
End Try
Return userList
End Function
Maybe helpful because related(you're also reusing the connection): ExecuteReader requires an open and available Connection. The connection's current state is Connecting
It will be something like this.
Public Function OpenMysqlCon() As MySqlConnection
Dim mMysqlconnection As MySqlConnection()
Try
Dim strconDB As String = "server='192.168.100.2'; database='mydb';Port=3306; UID='epb'; password='hahaha'; pooling=true"
mMysqlconnection = New MySqlConnection
mMysqlconnection.ConnectionString = strconDB
mMysqlconnection.Open()
Catch exceptionThatICaught As System.Exception
mMysqlconnection = Nothing
End Try
Return mMysqlconnection
End Function
Private Sub frmTest_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim con As MySqlConnection = OpenMysqlCon
If con Is Nothing Then
MessageBox.Show("connection not available at the moment, please try again later")
'Me.Close 'uncomment if the app should end
End If
End Sub
edit - this is not tested
Using con As MySqlConnection = OpenMysqlCon
If con Is Nothing Then
MessageBox.Show("connection not available at the moment, please try again later")
'Me.Close 'uncomment if the app should end
Else
'your code
End If
End Using

Accessing "all" declared variables in Class1.vb to many forms of a solution in vb.net

After a series of downloading connectors && some plugins, I finally managed to connect xampp to VB.Net. Though I found it very time-consuming/hassle everytime I put a connection string to each form that requires SQL insert and select statements So I came up with the idea of creating a Class1.vb and place there all the connection strings to xampp. So that everytime I created I new form, all I have to do is to import Class1.vb to each form so I could access the Dim conn As New MySqlConnection which as I have mentioned is declared on Class1.vb
Though, somehow I get connected with MYSQL most of the variables including one that bears the name of the dbtable cannot be access.
Let me show you what's inside my Class1.vb
Public Class Class1
Dim conn As New MySqlConnection
Dim command As MySqlCommand
Dim reader As MySqlDataReader
Public Sub mysqlConnect()
If Not conn Is Nothing Then conn.Close()
conn.ConnectionString = String.Format('connectionString for Dbname,server,uid,pword)
Try
conn.Open()
MessageBox.Show("Connected!")
Catch x As Exception
MsgBox(x.Message)
End Try
conn.Close()
end sub
end class
Inside Form1.vb
Public Class Form1
Dim newCon as New Class1
Private Sub Form2_Load
newCon.mysqlConnect()
'Note: mysqlConnect() is a function declared in Class1.vb
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
conn.Open()
Catch x As Exception
End Try
Dim command As New MySqlCommand(String.Format("INSERT STATEMENT"))
command.ExecuteNonQuery()
conn.Close()
End Sub
But the variables I indicate on Button1_Click aren't working. It's as if it cannot read some functions of the Public Sub Connect()
Though, as I have mentioned earlier, the Msgbox("Connected") did work which means that I am totally connected with my DB.
Any ideas, my friends?
Your comments are appreciated. Thanks in advance.
Two common solutions are:
1) Change your Class1 to have a "Factory method" which will give you an open connection.
2) Wrap your connection inside of your class
Example 1:
Public Class Class1
Dim conn As New MySqlConnection
Dim command As MySqlCommand
Dim reader As MySqlDataReader
Public Shared Function mysqlConnect() AS MySqlConnection
If Not conn Is Nothing Then conn.Close()
conn.ConnectionString = String.Format('connectionString for Dbname,server,uid,pword')
Try
conn.Open()
''MessageBox.Show("Connected!")
Catch x As Exception
MsgBox(x.Message)
End Try
''conn.Close() ''This must be done by your calling function now
''btw, if you forget, it may cause connection leaks, which are evil
Return conn
End function
End class
Example 2:
Public Class Class1
Public conn As MySqlConnection
Dim command As MySqlCommand
Dim reader As MySqlDataReader
''open the connection in the constructor
Sub New()
conn = New MySqlConnection
conn.ConnectionString = String.Format('connectionString for Dbname,server,uid,pword')
Try
conn.Open()
''MessageBox.Show("Connected!")
Catch x As Exception
MsgBox(x.Message)
End Try
End Sub
''close the connection in the destructor
Protected Overrides Sub Finalize()
conn.Close() ''automatically runs when this class is garbage collected
conn.Dispose()
End Sub
End class

Access to MySQL after closing connection

I have a problem with access to my datebase MySQL after closing it. I use Windows Form and MySql Connector from MySql official website to connect to datebase. I use MySQL in XAMPP.
If I open my connection I can do a simple query. But when I close a connection I can still do this query. Why?
Here is my code:
Imports MySql.Data.MySqlClient
Public Class Form1
Dim polaczenieMySql As New MySqlConnection
Dim mySQL As PolaczenieMySQL
Public Sub New()
InitializeComponent()
mySQL = New PolaczenieMySQL(Me)
End Sub
Private Sub btnPolaczMySQL_Click(sender As Object, e As EventArgs) Handles btnPolaczMySQL.Click
mySQL.Polacz()
End Sub
Private Sub RozlaczMySQL_Click(sender As Object, e As EventArgs) Handles btnRozlaczMySQL.Click
mySQL.Rozlacz()
End Sub
Private Sub btnZapytanie_Click(sender As Object, e As EventArgs) Handles btnZapytanieMySQL.Click
Dim zapytanie As String = "SELECT title, price, book_id from books"
mySQL.WykonajZapytanie(zapytanie)
End Sub
End Class
And my connection class:
Imports MySql.Data.MySqlClient
Public Class PolaczenieMySQL
Dim polaczenie As MySqlConnection = New MySqlConnection()
Dim glowneOkno As Form1
Public Sub New(form As Form1)
glowneOkno = form
End Sub
Public Sub Polacz()
polaczenie.ConnectionString = ("server=localhost;user id=root;password=;database=test")
Try
polaczenie.Open()
MessageBox.Show("Połączono z bazą danych MySQL.")
glowneOkno.labelPolaczenieMySQL.Text = "Połączono"
glowneOkno.labelPolaczenieMySQL.ForeColor = Color.Green
Catch myerror As MySqlException
MessageBox.Show("Nie udało się połączyć z bazą danych MySQL: " & myerror.Message)
End Try
End Sub
Public Sub Rozlacz()
Try
polaczenie.Close()
MessageBox.Show("Rozłączono z bazy danych MySQL.")
glowneOkno.labelPolaczenieMySQL.Text = "Nie połączono"
glowneOkno.labelPolaczenieMySQL.ForeColor = Color.Red
Catch myerror As MySqlException
MessageBox.Show("Błąd rozłączenia z bazy danych MySQL: " & myerror.Message)
Finally
polaczenie.Dispose()
End Try
End Sub
Public Sub WykonajZapytanie(ByVal zapytanie As String)
Dim SDA As New MySqlDataAdapter
Dim dbDataSet As New DataTable
Dim bSource As New BindingSource
Try
Dim komenda As MySqlCommand = New MySqlCommand(zapytanie, polaczenie)
SDA.SelectCommand = komenda
SDA.Fill(dbDataSet)
bSource.DataSource = dbDataSet
glowneOkno.DataGridViewMySQL.DataSource = bSource
SDA.Update(dbDataSet)
Catch ex As MySqlException
MessageBox.Show("Nie jesteś połączony z bazą")
End Try
End Sub
End Class
As I said before, after closing connection (mySQL.Rozlacz()) I can still do a query (mySQL.WykonajZapytanie(zapytanie)). What is wrong with this?
PS. Sorry for my polish names
If you look at the docs about the DbDataAdapter you could read this remark
The Fill method retrieves the data from the data source using a SELECT
statement. The IDbConnection object associated with the select command
must be valid, but it does not need to be open. If the IDbConnection
is closed before Fill is called, it is opened to retrieve data and
then closed. If the connection is open before Fill is called, it
remains open.
The MySqlDataAdapter inherits from the DbDataAdapter and there is no override of the Fill method, so it is the inherited class (DbDataAdapter) that works with the associated command, reopening the closed connection and then closing it.
EDIT
You asked also how to avoid this behavior, well you could add a boolean property to your class PolaczenieMySQL that maintains the state of your MySqlConnection
Private _isDead As Boolean
Public Property IsDead() As Boolean
Get
Return _isDead
End Get
Private Set(ByVal value As String)
_isDead = value
End Set
End Property
Now you could set this property to False when you open the connection and True when you close it.
Then check its value before executing the WykonajZapytanie sub
Public Sub WykonajZapytanie(ByVal zapytanie As String)
Dim SDA As New MySqlDataAdapter
Dim dbDataSet As New DataTable
Dim bSource As New BindingSource
if Me.IsDead Then
Throw new Exception("Invalid usage of this class")
End If
......
End Sub
Notice that there is a simpler check using the MySqlConnection property State
if polaczenie.State <> ConnectionState.Open Then
......
but, given the fact that in your Rozlacz method you dispose the connection I suggest to implement the first workaround.
Finally, I really think that you should change the whole pattern of usage. The connection should be opened, used and closed in the same method where it is required. Your actual infrastructure render this impossible. It is better to get rid of the Polacz and Rozlacz and use the mentioned pattern without the need of a global variable for the connection.

Fatal Error Encounter During Command Execution MySQL VB

ijust finish my code for inserting data using the vb and mySQL but when i run my webpage it seem have an error Fatal Error Encounter During Command Execution . Please help some how to solve it. below is my code.
Imports System.Data.SqlClient
Imports MySql.Data.MySqlClient
Partial Class Request
Inherits System.Web.UI.Page
Dim MessageBox As Object
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
txt1.Focus()
txt2.Focus()
txt3.Focus()
txt4.Focus()
txt5.Focus()
txt6.Focus()
txt7.Focus()
ddl1.Focus()
ddl2.Focus()
ddl3.Focus()
ddl4.Focus()
End Sub
Protected Sub btnsubmit_Click(sender As Object, e As EventArgs) Handles btnsubmit.Click
'Create sql connection and fetch data from database based on employee id
Dim conn As New MySql.Data.MySqlClient.MySqlConnection
Dim strConnectionString As String = ConfigurationManager.ConnectionStrings("testConnectionString").ConnectionString
Try
conn.ConnectionString = strConnectionString
conn.Open()
Catch ex As MySql.Data.MySqlClient.MySqlException
MessageBox.Show(ex.Message)
End Try
' Dim cr_id As String
' cr_id = "CR004"
Dim iReturn As Boolean
Using SQLConnection As New MySqlConnection(strConnectionString)
Using sqlCommand As New MySqlCommand()
sqlCommand.Connection = SQLConnection
With sqlCommand
.CommandText = "INSERT INTO cr_record(idcr_record,Emplid,Nama,date,DeptDesc,email,change,reasonchange,problem,priority,reasondescription,systemrequest) VALUES (#IDCR,#Emplid,#Nama,#date,#DeptDesc,'#email,#change,#reasonchange,#problem,#priority,#reasondescription,#systemrequest)"
' .CommandTimeout = 5000000
.CommandType = Data.CommandType.Text
.Parameters.AddWithValue("#Emplid", txt1.Text)
.Parameters.AddWithValue("#Nama", TextBox1.Text)
.Parameters.AddWithValue("#date", txt5.Text)
.Parameters.AddWithValue("#DeptDesc", txt2.Text)
.Parameters.AddWithValue("#email", txt4.Text)
.Parameters.AddWithValue("#change", ddl2.Text)
.Parameters.AddWithValue("#reasonchange", txt6.Text)
.Parameters.AddWithValue("#problem", ddl3.Text)
.Parameters.AddWithValue("#priority", rbl1.Text)
.Parameters.AddWithValue("#reasondescription", txt7.Text)
.Parameters.AddWithValue("#systemrequest", ddl4.Text)
End With
Try
SQLConnection.Open()
' sqlCommand.ExecuteNonQuery()
sqlCommand.ExecuteNonQuery()
iReturn = True
MsgBox("Added Successfully")
Catch ex As MySqlException
MsgBox(ex.Message.ToString & Err.Description)
iReturn = False
Finally
SQLConnection.Close()
End Try
End Using
End Using
Return
End Sub
End Class
you probably forgot to add this parameter #IDCR
.Parameters.AddWithValue("#IDCR", toyourvariable)
Syntax error in your query:
[...snip...]tDesc,'#email,#change,#rea[...snip...]
^---mis-placed quote.
Reserved words:
[...snip...]c,email,change,reasonc[...snip...]
^^^^^^---- quote with backticks: `change`
Solution that i used and it really works.
This error is mostly caused by a MISSING or Incorrectly Spelled Parameter declaration. eg. #FirstName mistakenly spelled for #FirtName.
Make sure that all the parameters that are declared in the sql query are all declared in the AddwithValue Parameter declaration. (It helps to count the query versus the Addwithvalues).
The best solution is for visual studio to provide information about the missing Parameter. Use a Try-Catch block. In the catch block use Messagebox.show(ex.Innerexception.Message) instead of Messagebox.show(ex.message). This will show the exact Parameter that is missing. eg. below
Try
conCommand.Parameters.Addwithvalue("#FirstName", txtFirstName.text)
conCommand.Parameters.Addwithvalue("#MiddleName", txtMiddleName.text)
conCommand.Parameters.Addwithvalue("#LastName", txtLastName.text)
conCommand.Parameters.Addwithvalue("#PhoneNo", txtPhoneno.text)
catch ex as exception
Messagebox.show(ex.innerexception.Message)
End Try
Hope this helps. Its really great that we share our ideas in the world of programming.