Oracle DataReader error because already open - vb.net

I get the following error:
There is already an open DataReader associated with this Command which must be closed first.
Exception Details: System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
And this is my code so far:
Public Function GetPrice() As Decimal
Dim aParams(1) As String
Dim dPrice As Decimal
aParams(0) = Me.ID
aParams(1) = Me.Date
With GetDb().GetRsWithSqlId("GET_PRICE", aParams)
If .Read() Then
dPrice = Convert.ToDecimal(IIf(TypeOf .Item("TS_PRICE") Is DBNull, 0.0, .Item("TS_PRICE")))
End If
.Close()
End With
Return dPrice
End Function
Public Function GetRsWithSqlId(ByVal sId As String, ByVal arrParams() As Object) As OleDbDataReader
Dim i As Integer
If m_oOleDbConnection.State <> ConnectionState.Open Then
If Not Connect() Then Throw New ArgumentException("Can't connect to database!" & Chr(13) & "LastError: " & LastError())
End If
m_oOleDbCommand.Parameters.Clear()
m_oOleDbCommand.CommandType = CommandType.Text
m_oOleDbCommand.CommandText = GetSql(sId)
If Not IsNothing(m_oOleDbTransaction) Then
m_oOleDbCommand.Transaction = m_oOleDbTransaction
End If
For i = 0 To arrParams.GetLength(0) - 1
m_oOleDbCommand.Parameters.Add(New OleDbParameter("?", arrParams(i)))
Next
Return m_oOleDbCommand.ExecuteReader()
End Function
The error message says that the DataReader is already in use with another command on the same connection, but I can't figure out where the reader is open.
Is there a solution to close the DataReader if it is open or to avoid using DataReader? My understanding is that without DataReader many commands can be used on the same connection at the same time or?

Related

"No value given for one or more required parameters" error using OleDbCommand

I am trying to update a record in MS Access using VB.net. This code will be under the "Delivered" button. When I try to run it, it shows the "No value given for one or more required parameters" error. Here is my code:
Private Const strConn As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Traicy\Downloads\MWL(11-30-2021)\MadeWithLove\MadeWithLove\MadeWithLove.mdb;"
ReadOnly conn As OleDbConnection = New OleDbConnection(strConn)
Dim cmd As OleDbCommand
Public Sub DeliveredUpdate()
Const SQL As String = "UPDATE DELIVERY SET delivery_status = #status"
cmd = New OleDbCommand(SQL, conn)
' Update parameter
cmd.Parameters.AddWithValue("#status", "Delivered")
' Open connection, update, then close connection
Try
conn.Open()
If cmd.ExecuteNonQuery() > 0 Then
MsgBox("The delivery status was successfully updated.")
End If
conn.Close()
Catch ex As Exception
MsgBox(ex.Message)
conn.Close()
End Try
End Sub
Do not declare connections or commands outside of the method where they are used. These database objects use unmanaged resources. They release these resources in their Dispose methods. The language provides Using blocks to handle this.
As mentioned in comments by Andrew Morton, you should have a Where clause to tell the database which record to update. This would contain the primary key of the record. I guessed at a name for the field, OrderID. Check your database for the real field name.
Access does not use named parameters but you can use names for readability. Access will be able to recognize the parameters as long as they are added to the Parameters collection in the same order that they appear in the sql string. In some databases the Add method is superior to AddWithValue because it doesn't leave the datatype to chance.
It is a good idea to separate your database code from your user interface code. If you want to show a message box in your Catch put the Try blocks in the UI code. This way your function can be used in a web app or mobile app without rewriting.
Public Function DeliveredUpdate(ID As Integer) As Integer
Dim recordsUpdated As Integer
Dim SQL As String = "UPDATE DELIVERY SET delivery_status = #status Where OrderID = #Id;"
Using conn As New OleDbConnection(strConn),
cmd As New OleDbCommand(SQL, conn)
cmd.Parameters.Add("#status", OleDbType.VarChar).Value = "Delivered"
cmd.Parameters.Add("#Id", OleDbType.Integer).Value = ID
conn.Open()
recordsUpdated = cmd.ExecuteNonQuery
End Using 'closes and disposes the command and connection
Return recordsUpdated
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim retVal As Integer
Dim id As Integer = 1 'not sure where you are getting this value from
Try
retVal = DeliveredUpdate(id)
Catch ex As Exception
MsgBox(ex.Message)
End Try
If retVal > 0 Then
MsgBox("The delivery status was successfully updated.")
End If
End Sub

"Connection was not closed. Connection's current State was open"- Ms Access Visual Basic- Visual Studio 2010

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.

the connectionstring property has not been initialized in vb.net

Everytime I click the button where the sub procedure execute, I'm getting the error "the connection string property has not been initialized"
Here is my code
Sub CheckExistingExp()
Dim aexpcheckifexisting As New DataSet
Dim bexpcheckifexisting As New OleDb.OleDbDataAdapter
Dim sqlcheck As String
Dim duplicateexp As Integer
sqlcheck = "select count(exp_doc) vcount from csap_exph where exp_doc = '" & RQuote(txtExpDoc.Text) & "' and status = 'A'"
bexpcheckifexisting = New OleDb.OleDbDataAdapter(sqlcheck, con)
bexpcheckifexisting.Fill(aexpcheckifexisting, "checkduplicateexp")
duplicateexp = aexpcheckifexisting.Tables("checkduplicateexp").Rows(0).Item("vcount")
If duplicateexp > 0 Then
If MsgBox("Expense Doc is already existing, are you sure you want to tag it as posted?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
Approve_Expense()
Else
con.Close()
End If
End If
End Sub
What should I do to solve this?
Thanks.
Let alone the connection string which is missing, where did you open con for you to close it? [con.open()] and if your user hits MsgBoxResult.Yes your connection would stay open cause con.Close() is only called if duplicateexp <= 0.
dispose your con at the end of your code or use using which closes it automatically and use a try-catch to catch any errors.
have your connection string somewhere in app.config or make it public in a class or module or whatever you prefer and make your string = that value and open your connection at the beginning of the sub.

VB.NET WCF - Error Using my function

I have a function to get information on a SQL Server Table. I know the function is correct and returning everything as suposed too (I used msgBox to check it). The problem is when I try to use that function it displays an error:
My WCF Function:
Public Function GetCLInfo(ByVal cl_ID As Integer) Implements SQLOperator.GetCLInfo
Dim CLInfo(7) As String
Try
SQLCon.ConnectionString = SQLConString
SQLCon.Open()
SQLCMD = New SqlCommand("Select * from dbo.cl Where ID=" & cl_ID & ";", SQLCon)
SQLDataReader = SQLCMD.ExecuteReader()
While SQLDataReader.Read
CLInfo(0) = SQLDataReader("ID")
CLInfo(1) = SQLDataReader("Name")
CLInfo(2) = SQLDataReader("Address")
CLInfo(3) = SQLDataReader("Contact")
End While
Return CLInfo
Catch ex As Exception
MsgBox("Error: " & Environment.NewLine & ex.ToString)
CLInfo(0) = "False"
Return CLInfo
Finally
SQLCon.Close()
SQLCon.Dispose()
End Try
Return CLInfo
End Function
In the picture you can see aswell how I'm trying to use the function.
Can someone kindly tell me what am I doing wrong?
Your problem is that you are calling a function to return string array and program doesn't catch by itself. As #Matt Wilko point out use Option Strict On.
Second if you have more than one client your logic fails.
For I as integer = 1 to AllCl
Dim cl(7) as String
cl = Service.GetClInfo(I)
next
Above code will reset every each time, plus when you leave for loop you are loosing access to cl.
Ugly fix could be multidimensional array.
Now you should specify your return type
Public Function GetCLInfo(ByVal cl_ID As Integer) As String() Implements SQLOperator.GetCLInfo

Why is my reader stuck in infinite loop [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Can anyone please explain why this is stuck in an infinite loop? I put this under a button and it worked fine. But when I put this in a class and instantiate the class, it gets stuck in an infinite loop. I assume it gets stuck in the loop because when I add breakpoints, it wont go further than inside the loop. It doesn't even get passed "End While", but if i put this code under a button click in ASP.NET it works just fine. What am I doing wrong?
Please don't criticize about "SQL injection" with the way I'm passing values to my database, because this isn't going to be a public thing and I'm well aware of that.
Imports System.Data
Imports System.Data.SqlClient
'Step 1: Select the device ID
Function SelectDevice(d As String, b As String, m As String, o As String) As String
' Try
'Connect to database
Dim xcitoDBConnection As SqlConnection
xcitoDBConnection = New SqlConnection("Data Source=NOTDISPLAYED;" + "Initial Catalog=NOTDISPLAYED;" + "Integrated Security=True")
Dim GetDeviceID As String = "SELECT DISTINCT(Identifier) FROM Support.Devices WHERE DeviceType='" & d & "' AND Brand = '" & b & "' AND Model = '" & m & "' AND OS = '" & o & "'"
Dim command As SqlCommand = New SqlCommand(GetDeviceID, xcitoDBConnection)
xcitoDBConnection.Open()
'command.ExecuteScalar()
Dim reader As SqlDataReader
reader = command.ExecuteReader(CommandBehavior.CloseConnection)
Dim GetID As String
While reader.Read()
GetID = reader("Identifier").ToString
Return GetID
End While
xcitoDBConnection.Close()
' Catch ex As ApplicationException
' ex.Source = ("Selection Error")
' Throw ex
' Finally
'End Try
End Function
End Class
write
reader = command.ExecuteReader()
instead of
reader = command.ExecuteReader(CommandBehavior.CloseConnection)
as you closed the connection at before return.
and return end of the function
follow this
Public Sub CreateCommand(ByVal queryString As String, _
ByVal connectionString As String)
Dim GetID As String
Using connection As New SqlConnection(connectionString)
connection.Open()
Dim command As New SqlCommand(queryString, connection)
Dim reader As SqlDataReader = command.ExecuteReader()
While reader.Read()
GetID = reader(0).ToString
End While
End Using
Return GetID
End Sub