in vb.net, there are some applications that use adodb to access a mysql server.
private adoconnect as new adodb.connection
public adors as new adodb.recordset
public function returnadors(byval column as string) as string
return adors.fields(column).value.tostring
end function
Public Function ReadData(ByVal strQuery As String, Optional ByVal strWhere As String = vbNullString) As Boolean
Try
If ADOConnect.State = ConnectionState.Open Then Call CloseConnection()
ADOConnect.Open(dsn, user, pass)
ADORS.Open(strQuery, ADOConnect, ADODB.CursorTypeEnum.adOpenDynamic)
If not ADORS.EOF Then Return True
Catch ex As Exception
msgbox(ex)
End Try
Return False
End Function
public sub closeconnection()
if adoconnect.state = connectionstate.open then adoconnect.close
end sub
now lets say we wanted to populate a textbox with something from the database:
if readdata("SELECT NAME FROM USERS WHERE ID = 1") then
me.textbox1.text = returnadors("NAME")
end if
call closeconnection
re writing these functions is a big task - and I am not interested in doing it unless absolutely needed.
Here is my problem though.
even if the connection is closed (and i have stepped through the code, it closes)
The connection is still visible on the sql server in a sleep state
why? and how can i make sure that the connection is closed.
thanks
Add the following to your ConnectionString:
Pooling=False;
I don't have much experience with exactly what you are doing, but this is usually the path I take with sqlserver connections. Using will automatically close your connection.
Using ADOconnect
'operations
End Using
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.
I'm attempting to overload the "Delete" method of a TableAdapter (approach). How can I execute an SQL statement from 'here' to handle the delete?
I've got:
Namespace AFL_BackendDataSetTableAdapters
Partial Class Log_entry_unitTableAdapter
Public Overloads Function Delete(ByVal LogEntryID As Integer) As Integer
Dim SQL As String
SQL = "DELETE FROM log_entry_unit WHERE log_entry_unit_id=" & LogEntryID
'?????.Execute SQL
Return 0
End Function
End Class
End Namespace
The overload is working fine, but I don't know how to do the hard part and actually manipulate the data from here. Previously, I've just gone into the Dataset Designer and manually updated the generated methods to work like I want them, but whenever I use the wizard to regenerate the dataset, that (as expected) gets overwritten.
I've previously only ever manipulated Data using the generated methods, and now I'm stuck.
EDIT w/ Final Answer
Based on William's help below here's the final working solution (Note I just had to use OleDb instead of SQL since my Dataset is Access:
Imports System.Data.OleDb
Namespace AFL_BackendDataSetTableAdapters
Partial Class Log_entry_unitTableAdapter
Public Overloads Function Delete(ByVal LogEntryID As Integer) As Integer
Dim queryString As String = "DELETE FROM log_entry_unit WHERE log_entry_unit_id=" & LogEntryID
Dim command As New OleDbCommand(queryString, Connection)
Dim r As Integer
Try
Connection.Open()
r = command.ExecuteNonQuery()
Catch ex As Exception
MsgBox(ex.Message)
r = 0
Finally
Connection.Close()
End Try
Return r
End Function
End Class
End Namespace
I hardcoded a connection string for reference only. This should be in a config file. As an example:
Dim connectionString As String = _
"Data Source=(local);Initial Catalog=YourDatabase;" _
& "Integrated Security=true"
Dim queryString As String = "DELETE FROM log_entry_unit WHERE log_entry_unit_id=" & LogEntryID
' Create and open the connection in a using block. This
' ensures that all resources will be closed and disposed
' when the code exits.
Using connection As New SqlConnection(connectionString)
' Create the Command
Dim command As New SqlCommand(queryString, connection)
' Open the connection in a try/catch block.
Try
connection.Open()
command.ExecuteNonQuery()
Catch ex As Exception
' handle exception here
End Try
End Using
EDIT
I probably should of mentioned you will probably want to fill your adapter again after the delete.
In my VB.Net program I have found two (2) warnings shows the following messages:
Function doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used
help me where is the problem and to fix it. The following snapshot is where the warning error indicates:
The Firs Warning near 'End Function'
'Executes SQL commands to the system database
Public Function ExecSQL(ByVal sql As String)
Dim com As New MySqlCommand(sql)
Try
RefreshConnection()
com.Connection = con
com.ExecuteNonQuery()
Catch ex As Exception
Return ex
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error")
End Try
End Function
The Second Waring near 'End Function'
'Get the value of an specific field in a given sql string
Public Function GetField(ByVal sql As String, ByVal field As String)
Try
RefreshConnection()
Dim com As New MySqlCommand(sql, con)
Dim dReader As MySqlDataReader = com.ExecuteReader
While dReader.Read
GetField = dReader(field).ToString
End While
dReader.Close()
Catch ex As Exception
Return ex
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error")
End Try
End Function
This occurs because in the exception handler you actually return the exception object ex. You're not returning anything if no exception occurs. You could explicitly add Return Nothing just above Catch ex as Exception, but I guess from the message that VB is doing that automatically for you...
By the way: What's the point returning the exception to the caller? Put the message box into the calling method and wrap your call in Try-Catch there. A method that's obviously not meant to interact with the user shouldn't show messages at all. And then you can just pass the exception up until you end up the presentation layer.
Long story short: No message boxes in business logic. User information only in presentation layer.
After reading your second method: Things are even worse here! If the data reader has rows, you set the result of the method to the last (!) result you found (this is a WTF in itself, but another story). If an error occurs, the result is an object of type Exception, so the calling code even needs to make sure to decide whether the result of the function call is actually a field value or an exception!
This is really bad design my friend.
You asked for fixed code:
'Executes SQL commands to the system database
Public Sub ExecSQL(ByVal sql As String)
Dim com As New MySqlCommand(sql)
RefreshConnection()
com.Connection = con
com.ExecuteNonQuery()
End Sub
'Get the value of an specific field in a given sql string
Public Function GetField(ByVal sql As String, ByVal field As String)
RefreshConnection()
Dim com As New MySqlCommand(sql, con)
Dim dReader As MySqlDataReader = com.ExecuteReader
GetField = Nothing
While dReader.Read
GetField = dReader(field).ToString
End While
dReader.Close()
End Function
There are several flaws here. In the interest of brevity, I'll just post some improved code:
'Executes SQL commands to the system database
Private Function ExecSQL(ByVal sql As String, ByVal params As IEnumerable(Of MySqlParameter))
Using cn As New MySqlConnection(GetConnectionString()), _
com As New MySqlCommand(sql, cn)
For Each param As MySqlParameter in params
com.Parameters.Add(param)
Next param
cn.Open()
com.ExecuteNonQuery()
End Using
End Function
'Get the value of an specific field in a given sql string
Private Function GetField(Of T)(ByVal sql As String, ByVal params As IEnumerable(Of MySqlParameter), ByVal field As String) As T
Using cn As New MySqlConnection(GetConnectionString())
com As New MySqlCommand(sql, cn)
For Each param As MySqlParameter In params
com.Parameters.Add(param)
Next param
cn.Open()
Using rdr As MySqlDataReader = com.ExecuteReader()
While rdr.Read()
Return CType(rdr(field), T)
End While
End Using
End Using
Return Nothing
End Function
I'm having an issue with my vb.net program. The issue is coming from my stored procedure classes. I have tested the stored procedures in the SQL database I'm working with, and all of them are working.
I also want to note that I did copy and paste the SP's name over to the SQL server and executed it and it ran perfectly.
EXEC dbo.ksp_Get_Available_Statuses
In the program itself only one SP class is working. The following is that code:
Imports System.Data.SqlClient
Public Class Add_Term
Public Function addTerm(ByVal term As String, ByVal definitionSource As Integer, ByVal formatNote As String, ByVal definition As String, ByVal authorization As String, ByVal addReason As String)
Dim connection As SqlConnection = DataConnection.getProperityDBConnection
Dim insertCommand As New SqlCommand("dbo.ksp_Add_Term", connection)
insertCommand.CommandType = CommandType.StoredProcedure
insertCommand.Parameters.AddWithValue("#term", term)
insertCommand.Parameters.AddWithValue("#definitionSource", definitionSource)
insertCommand.Parameters.AddWithValue("#formatNote", formatNote)
insertCommand.Parameters.AddWithValue("#definition", definition)
insertCommand.Parameters.AddWithValue("#authorization", authorization)
insertCommand.Parameters.AddWithValue("#addReason", addReason)
Try
connection.Open()
Dim count As Integer = insertCommand.ExecuteNonQuery()
If count > 0 Then
Return True
Else
Return False
End If
Catch ex As Exception
Throw ex
Finally
connection.Close()
End Try
End Function
End Class
Here is the code I'm working on fixing, but it's not working. I don't see what I'm doing wrong and it's driving me nuts. I need a second pair (if not more) eyes on it.
Imports System.Data.SqlClient
Public Class Get_Avaliable_Statuses
Public Function getAvailableStatuses()
Dim connection As SqlConnection = DataConnection.getProperityDBConnection
Dim insertCommand As New SqlCommand("dbo.ksp_Get_Available_Statuses", connection)
insertCommand.CommandType = CommandType.StoredProcedure
Try
connection.Open()
Dim count As Integer = insertCommand.ExecuteNonQuery()
If count > 0 Then
Return True
Else
Return False
End If
Catch e As Exception
Throw e
Finally
connection.Close()
End Try
End Function
End Class
The following is the error that is popping up for those that want to know the exact wording:
Error Message Screen Shot.
As allows, any help is appreciated.
do you have a
set nocount on
in your sproc? I guess ExecuteNonQuery cannot return the number of affected rows then ...
Supervisor looked over my code to assist. Realized it should be Excute Reader and not ExecuteNonQuery. I'm looking for information, not inserting new sources.
Thanks for the help!
Can you please tell me what's wrong with this code?
Do I need to use DataAdapter to insert into a table?
I know the connectionString is ok, because I tested it on the Server Explorer.
Dim mydao As New Connection
Dim connectionString As String = mydao.GetConnectionString()
Dim connection As New SqlConnection(connectionString)
Dim cmd As New SqlCommand
Public Function add(ByVal area As String, ByVal user As String) As Integer
cmd.CommandText = "INSERT into Area (Area, user) VALUES ('" + area + "','" + user + "')"
Try
connection.Open()
Dim cant As Integer = cmd.ExecuteNonQuery()'it throws exception here
connection.Close()
Return cant
Catch ex As Exception
Console.WriteLine(ex.Message)
Return 0
End Try
End Function
The above code fails just after ExecuteNonQuery() and canĀ“t figure why.
TARGET FIELDS (SQL Server 2008):
AREA varchar(100) NOT NULL ,
USER varchar(100) NOT NULL
The exception I receive is: Connection property has not initialized
There's a few issues with this code.
The most significant is that you aren't setting the Command's Connection property, so the command has no way of knowing how to connect to the database.
I would also strongly recommend utilizing using, and also parameterizing your query:
Finally, don't declare the connection and command outside of the function unless you need to. You should only keep the connection and command around for as long as you need them.
So your function would end up looking like:
Public Function add(ByVal area As String, ByVal user As String) As Integer
Dim mydao As New Connection
Using connection As New SqlConnection(mydao.ConnectionString())
Using command As New SqlCommand()
' Set the connection
command.Connection = connection
' Not necessary, but good practice
command.CommandType = CommandType.Text
' Example query using parameters
command.CommandText = "INSERT into Area (Area, user) VALUES (#area, #user)"
' Adding the parameters to the command
command.Parameters.AddWithValue("#area", area)
command.Parameters.AddWithValue("#user", user)
connection.Open()
Return command.ExecuteNonQuery()
End Using ' Dispose Command
End Using ' Dispose (and hence Close) Connection
End Function
Note that currently, you will be returning 0 all the time. Rather than having to check the value returned from the function, the above example will simply throw an exception. This makes for slightly cleaner code (as the caller would have to understand that 0 is an error condition), and, if you needed to handle the exception, simply wrap the call to this function in a Try-Catch block