I'm trying to connect to a database and keep the connection open for any amount of user activity/queries within the database. Currently I have a connection that opens and closes for any query (save, update, etc...) which requires the logon process to the back-end every time the user saves etc... Is there a way to simply connect and leave the connection open so there won't be a lag time when running the query due to the logon process? This is what I'm using:
Private sConStrFormat As String = "Provider=TDOLEDB;Data Source=TDDEV;Persist Security Info=True;User ID={0};Password={1};Default Database=bcpm_ddbo;Session Mode=ANSI;"
Private Sub cmdsave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdsave.Click
Dim sSQL As String
Dim sConStr As String
Dim user As String
Dim pass As String
user = txtuser.Text
pass = txtpass.Text
Dim UserName As String = user
Dim Password As String = pass
sConStr = String.Format(sConStrFormat, UserName, Password)
Using Con As System.Data.OleDb.OleDbConnection = New System.Data.OleDb.OleDbConnection(sConStr)
Con.Open()
sSQL = "INSERT INTO LTC_FBS (CLM_NUM) VALUES ('" & Me.txtClaim.Text & "')"
Dim cmdins As New System.Data.OleDb.OleDbCommand(sSQL, Con)
cmdins.ExecuteNonQuery()
Con.Close()
End Using
End Sub
.Net automatically maintains a connection pool for you. According to MSDN, when you call Close() on the Connection the framework
releases the connection to the
connection pool, or closes the
connection if connection pooling is
disabled
In vb.net 4.5 do the following:
At the top straight after the class definer put in this line:
Public Shared conn As OdbcConnection
Then, in the subs where you want to use the connection use this line:
If conn Is Nothing Then conn = New OdbcConnection(<your_connection_string>): conn.Open()
Then the New OdbcCommand will use the existing connection without opening a new one. Don't close the connection in your script until you are quite certain you're finished with it (_Shutdown is a good spot and you're good to go.
This also solves problems with MySQL when constantly opening new connections causes the max connections error.
Instead of defining 'con' in the using statement, define it up above as a static variable. When the function is called, you can see if 'Con' has been assined or not. If not, you build your connection string and set Con = New OleDBConnection, and open it. Since it's a static variable, it will retain its value at the next call. Check that it's not nothing, and then use it right away. Make sure you don't call close in the routine or the connection will not remain open.
Related
My connection between my project and my Ms Access 2010 Database seems to be right at the moment of logging in with my project. However, After the first trial(if user and/or password are incorrect), when I try to log in again, the error is given. It says "Connection was not closed. Connection's current State was open". I just have found possible solutions for MySql service, but I'm using Ms Access database. The code where the error seems to be given is the following. Any suggestions?, please:
Public Function Validation()
da.Fill(dt)
connection.Open()
For Each DataRow In dt.Rows
If txtUser.Text = DataRow.Item(0) And txtPassword.Text = DataRow(1) Then
If cmbAccountType.Text = DataRow(2) Then
connection.Close()
Return True
End If
End If
Next
Return False
End Function
Why are you opening the connection in the first place? You're not using it between the Open and Close calls so what's the point? The Fill method will automatically open the connection if it's currently closed and then it will automatically close it again if it opened it, i.e. Fill and Update will open the connection if necessary and then leave it in its original state afterwards. Get rid of both the Open and Close calls.
To begin with, Function's in vb.net require a DataType. I have no idea what da.Fill(dt) is doing in this function. If you didn't have an open connection you wouldn't be able to fill anything but then on the next line you open some unknown connection from somewhere.
OleDb pays no attention to the names of parameters. The position of the parameters in the sql string must match the order that the parameters are added to the parameters collection.
Here is one approach.
Private ConnStr As String = "Your connection string"
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If Validation(txtUser.Text, txtPassword.Text, cmbAccountType.Text) Then
'Do something
End If
End Sub
Public Function Validation(UName As String, PWord As String, Type As String) As Boolean
Dim Count As Integer
Using cn As New OleDbConnection(ConnStr),
cmd As New OleDbCommand("Select Count(*) From SomeTable Where User = #User And Password = #Password And AccountType = #Type;", cn)
cmd.Parameters.Add("#User", OleDbType.VarChar).Value = UName
cmd.Parameters.Add("#Password", OleDbType.VarChar).Value = PWord
cmd.Parameters.Add("#Type", OleDbType.VarChar).Value = Type
cn.Open()
Count = CInt(cmd.ExecuteScalar)
End Using
If Count > 0 Then
Return True
End If
Return False
End Function
Of course you should NEVER store passwords as plain text.
This specific code ComboBox2.SelectedItem query has an error to my database. I think I'm missing something with this code ComboBox2.SelectedItem:
Private Sub UpdateCombo()
ComboBox2.Items.Clear()
SQLcon.Open()
Dim Command As SqlClient.SqlCommand = SQLcon.CreateCommand()
Command.CommandText = "Select productName From tblProductsStocks"
Dim SQLReader As SqlClient.SqlDataReader = Command.ExecuteReader()
While SQLReader.Read()
ComboBox2.Items.Add(SQLReader.Item("productName"))
End While
SQLcon.Close()
End Sub
Private Sub ComboBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox2.SelectedIndexChanged
SQLcon.Open()
Dim Command As SqlClient.SqlCommand = SQLcon.CreateCommand()
Command.CommandText = "Select * From tblProductsStocks WHERE productName=" & ComboBox2.SelectedItem
Dim SQLReader As SqlClient.SqlDataReader = Command.ExecuteReader()
SQLReader.Read()
TextBox1.Text = SQLReader.Item("productType")
TextBox2.Text = SQLReader.Item("productMass")
SQLcon.Close()
End Sub
Please turn on Option Strict. This is a 2 part process. First for the current project - In Solution Explorer double click My Project. Choose Compile on the left. In the Option Strict drop-down select ON. Second for future projects - Go to the Tools Menu -> Options -> Projects and Solutions -> VB Defaults. In the Option Strict drop-down select ON. This will save you from bugs at runtime.
Connections need to be disposed as well as closed to be returned to the connection pool. If there is an error, your code may not even close the connection. If you keep your database objects local, you can control that they are closed and disposed. Using...End Using blocks take care of this for you even if there is an error. In my code the Command is part of the Using block. Note the comma after the connection constructor.
You can pass the connection string directly to the constructor of the connection. Likewise pass the command text and the connection to the command constructor.
Use parameters. Not only does it avoids errors concatenating strings but it also avoids Sql injection. In your code, the selected item is meant to be a string but you have failed to add the surrounding single quotes. This is not needed when you use parameters. Command text is executable code to the server and a malicious user can enter things that would ruin you database. Parameters are considered as values by the server, not executable code so they are much safer.
Open the connection at the last possible moment, right before the .Execute... Connections are precious resources and need to be opened, closed and disposed as quickly as possible. The connection must be open as long as the reader is engaged. So I moved updating the user interface (the text boxes) to outside the using block.
Private Sub ComboBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox2.SelectedIndexChanged
Dim String1 As String = ""
Dim String2 As String = ""
Using SQLcon As New SqlConnection("Your connection string"),
Command As New SqlCommand("Select * From tblProductsStocks WHERE productName= #producName", SQLcon)
'Check your database for the actual datatype and field size
Command.Parameters.Add("#productName", SqlDbType.VarChar, 100).Value = ComboBox2.SelectedItem.ToString
SQLcon.Open()
Dim SQLReader As SqlClient.SqlDataReader = Command.ExecuteReader()
SQLReader.Read()
String1 = SQLReader.Item("productType").ToString
String2 = SQLReader.Item("productMass").ToString
End Using 'closes and disposes the connection and command
TextBox1.Text = String1
TextBox2.Text = String2
End Sub
I'm dusting off vb.net needs to work and I have a question that I hope you can clarify. My application require a connection with a database, now when the form is load I execute this function:
Sub OpenConnection()
Try
Dim connection As New Connection
Dim MysqlConn = connection.establishConnection()
MysqlConn.Open()
Catch myerror As MySqlException
MessageBox.Show("Connection failed: " & myerror.Message)
Finally
MysqlConn.Dispose()
End Try
End Sub
The problem's that connection and MysqlConn variable is used also in another function so I've declared this two variable as global. How you can see this variable are re-declared in the OpenConnection() 'cause I've a form where the user can change the settings connection string. Now if the software can't connect to the database for a wrong credentials the user change this into the setting form but if I remove connection and MysqlConn the application use the past instance of a class so even if the credentials are correct, not declaring a new instance of the connection the application can't connect. For the moment I've solved with a re-declaration inside the OpenConnection() but is this a good move? Is there a way to have the two global variables and invoke a new instance without redefine the function?
Connection class - EstablishConnection function
Public Function establishConnection()
Dim MysqlConn As MySqlConnection = New MySqlConnection()
Dim server_name = My.Settings.server_name
Dim username = My.Settings.username
Dim password = My.Settings.password
Dim database = My.Settings.database
MysqlConn.ConnectionString = "server=" & server_name & ";" _
& "user id=" & username & ";" _
& "password=" & password & ";" _
& "database=" & database & ";"
Return MysqlConn
End Function
How to redeclare an instance of a class?
Variables are declared.
Objects are instanced (instantiated).
They are never redeclared; another new one is just created. Take this line (similar to yours):
Dim connection As MySQLConnection
It declares a variable, giving it a name and type.
Dim connection As MySQLConnection = New MySQLConnection
The second part creates an instance - the New operator is the key: it creates a new instance. The short hand form you used does both at once and perhaps makes it unclear that 2 different operations - declaring a variable and creating an instance - are going on.
Apparently, you have a class named Connection to "manage" connections. But the top method, OpenConnection is just using it to set/reset some global object var. dbConnections should generally be created, used and disposed of.
A connection maker-helper like you have can prevent having connection strings
sprinkled all over the code. Eg:
Function GetMySQLConnection(Optional usr As String = "root",
Optional pw As String = "123456") As MySqlConnection
Dim conStr As String
conStr = String.Format("Server=localhost;Port=3306;Database={0};Uid={1}; Pwd={2};",
MySQLDBase, usr, pw)
Return New MySqlConnection(constr)
End Function
This might be part of a small class to hold the DBname and other log in info. But using it doesnt require a global var:
Sub GetSomeData(...)
Using dbCon As MySqlConnection = GetMySQLConnection()
...
dbCon.Open()
myDA.Fill(myDT)
...
End Using
End Sub
At the start, a new connection object is created for this set of operations, which exists only locally (in that method). The Using block assures that the connection is closed (and returned to the pool) and disposed of when you are done with it.
I want to let the users change the sql server connetion manually from a settings form because the application will be used in many company
i tried this:
i create a string in settings "sqlservername"
then in the loading form i put a textbox "txt_sqlservername" and savebutton
the button event
My.Settings.sqlservername = Me.txt_sqlservername.Text
My.Settings.Save()
MsgBox("Server Name Was Updated", MsgBoxStyle.Information, "Videos Database - New Server Name")
Me.Close()
and this is my connection string
Public SQLCon As New SqlConnection With {.ConnectionString = "Server=My.Settings.sqlservername;Database=Videos;User=sa;Pwd=123456;"}
when i open my main form nothing shown
any help?
You can give a form that asks for user input for the connection string and then save the connection string in the application settings.
You can use this connection string from the settings every time you define a connection in the application.
The string formatting is wrong where the connection is defined.Make correction like shown below:
Public SQLCon As New SqlConnection With {.ConnectionString = "Server=" & My.Settings.sqlservername & ";Database=Videos;User=sa;Pwd=123456;"}
I am trying to connection to MS SQL SERVER 2008 database (students), i want to make sure:
1) If connection string that i made is OK
Dim connectionString As New SqlConnection("server=X86ONX64; database=students; Integrated Security=True")
2) How can i check if dataset is producing any results?
Code:
Public Class Form1
'Connection String + DataAdaptor + DataSet
'Declared Outside Any Subroutines/Functions
Dim connectionString As New SqlConnection("server=X86ONX64; database=students; Integrated Security=True")
Dim dataAdaptor As New SqlDataAdapter()
Dim objdataSet As New DataSet()
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
dataAdaptor.SelectCommand = New SqlCommand()
dataAdaptor.SelectCommand.Connection = connectionString
dataAdaptor.SelectCommand.CommandText = "select * from basic_info;"
dataAdaptor.SelectCommand.CommandType = CommandType.Text
connectionString.Open()
dataAdaptor.Fill(objdataSet, "StudentInfo")
connectionString.Close()
grd.AutoGenerateColumns = True
grd.DataSource = objdataSet
grd.DataMember = "basic_info"
dataAdaptor = Nothing
connectionString = Nothing
End Sub
About your first question, If connection string that i made is OK
If you did not get any exceptions, you've successfully made the connection to your database.
About your second question.
There are two things you can do.
Debug the wrong way. (It works though)
MsgBox(objdataSet.Tables[0].Rows.Count);
Learn and debug the correct way.
Read these articles
Debugging Basics
Visual Studio Debugging
Debugging Basics: Breakpoints
Anyway, learn how to use the debugger properly, put a break point, analyse the objdataSet object in a watch window and see if any results are present.
1) If connection string that i made is OK
Easy way to verify connection strings is to connect using the "Server Explorer" in Visual Studio. Once you get a good connection, right-click on the connection and just grab the "Connection String" property.
2) How can i check if dataset is producing any results?
MsgBox(objdataSet.GetXML)
GetXML will return ALL the data in the dataset in XML format.
Also, don't globally declare variables if you don't need to.
Declare them closer, or not at all, like so...
Dim objdataSet As New Data.DataSet()
Using connectionString As New Data.SqlClient.SqlConnection("server=X86ONX64; database=students; Integrated Security=True")
With New Data.SqlClient.SqlDataAdapter()
.SelectCommand = connectionString.CreateCommand
.SelectCommand.CommandText = "select * from basic_info;"
.SelectCommand.CommandType = Data.CommandType.Text
.Fill(objdataSet, "StudentInfo")
End With
MsgBox(objdataSet.GetXML)
End Using
'Now put it in your dataset...'
Hope this helps.