Why is my reader stuck in infinite loop [closed] - sql

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

Related

Slow database query: Using VB.net connecting to Access

I have a program which will only allow a certain amount of concurrent users to use the program at one time. To do this I have a single table in an access database which holds each user that is using the program. Now although this does work the query seems to be running very slowly, I am certain it is something to do with the database functions as it was running fine before I implemented them.
Here are my functions:
Public Function openDB() As Boolean
cnn.Open()
Return True
End Function
Public Function closeDB() As Boolean
cnn.Close()
Return True
End Function
Then there is the function for checking the database. This is where I think it may be tripping up because I have 2 queries running here:
Public Function CheckLicence() As Boolean
Dim result As Boolean = HandleRegistry()
If result = True Then
Dim _table As String = "Users"
Dim query As String = "SELECT * FROM " & _table & " WHERE Machine_ID='" & CpuId() & "'"
Dim sizeQuery As String = "SELECT COUNT(*) FROM " & _table
Dim NoUsers As Integer = 0
Dim ds As New DataSet
Dim dr As OleDbDataReader
Dim cmd As New OleDbCommand(query, cnn)
dr = cmd.ExecuteReader
Dim sizeCdm As New OleDbCommand(sizeQuery, cnn)
NoUsers = sizeCdm.ExecuteScalar()
If dr.Read() Then
Return True
Else
If NoUsers < My.Settings.NoUsers Then
addToDB()
Else
MsgBox("Too many users are currently using this program. Clear a user and try again.")
Return False
End If
End If
Else
MsgBox("Your licence has expired, contact support to purchase a new licence.")
Return False
End If
Return True
End Function
And to add and remove I have to get the cpu id, I found the code for that on here somewhere it does work but maybe that could be the slow part, I dont actually know if this is the correct way of getting it.
Public Sub addToDB()
Dim _table As String = "Users"
Dim query As String = "INSERT INTO " & _table & " ([User], [Machine_ID]) VALUES (?,?)"
Dim ds As New DataSet
Dim cmd As New OleDbCommand(query, cnn)
cmd.Parameters.AddWithValue("?", Environment.UserName)
cmd.Parameters.AddWithValue("?", CpuId())
cmd.ExecuteNonQuery()
End Sub
Public Sub RemoveFromDB()
Dim _table As String = "Users"
Dim query As String = "DELETE * FROM " & _table & " WHERE Machine_ID='" & CpuId() & "'"
Dim ds As New DataSet
Dim cmd As New OleDbCommand(query, cnn)
cmd.ExecuteNonQuery()
End Sub
Private Function CpuId() As String
Dim computer As String = "."
Dim wmi As Object = GetObject("winmgmts:" &
"{impersonationLevel=impersonate}!\\" &
computer & "\root\cimv2")
Dim processors As Object = wmi.ExecQuery("Select * from " &
"Win32_Processor")
Dim cpu_ids As String = ""
For Each cpu As Object In processors
cpu_ids = cpu_ids & ", " & cpu.ProcessorId
Next cpu
If cpu_ids.Length > 0 Then cpu_ids =
cpu_ids.Substring(2)
Return cpu_ids
End Function
How about storing the cpuID globally and fetching only once. Also, use the Using construct on anything that needs to be disposed. Lastly, run a few StopWatches around your methods to see which one is slow or just debug through each one to find the slow method.
Answer:
How about storing the cpuID globally and fetching only once. Also, use the Using >construct on anything that needs to be disposed. Lastly, run a few StopWatches >around your methods to see which one is slow or just debug through each one to >find the slow method. – Andrew Mortimer
Moved the call for getting the cpuID to the program initialisation so that it runs on startup. This made it run much faster than it did before.

System.InvalidOperationException: ExecuteReader requires an open and available connection. The connection's current state is closed

I am having a problem with a customer service module which is in a different solution. the problem I think is in my method of calling or getting a connection
here is my class called DBConnForAccess
Imports System.Data.OleDb
Imports System.Data.Odbc
Public Class DBConnForAccess
Dim Conn As New OleDbConnection
Dim cmd As New OleDbCommand
Dim Trans As OleDbTransaction
Public Function DBConnect(ByVal filePath As String, pass As String)
Try
' open Database
'Conn = New SqlConnection("Data Source=" + ServerName + "\" + DBName + ";User ID=" + DBUsername + ";Password=" + DBPassword + ";Initial Catalog= '" + TB + "'")
Conn = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Jet OLEDB:Database Password=" + pass + ";")
' "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\mydatabase.mdb;Jet OLEDB:Database Password=MyDbPassword;"
If Conn.State = ConnectionState.Closed Then
Conn.Open()
End If
' create transaction
Trans = Conn.BeginTransaction
Return "Ok"
Catch ex As Exception
Return ex.Message
End Try
End Function
Public Sub ExecuteSQL(ByVal sql As String, ByVal ParamArray Obj() As Object)
' command Object
Dim CMD As New OleDbCommand(sql, Me.Conn, Me.Trans)
'add the parameters to the sql command
Dim I As Integer
For I = 0 To Obj.Length - 1
CMD.Parameters.AddWithValue("#" & I, Obj(I))
Next
'execute the sql
CMD.ExecuteNonQuery()
End Sub
Public Sub commit()
Me.Trans.Commit()
Me.Trans = Me.Conn.BeginTransaction
End Sub
Public Sub rollback()
Me.Trans.Rollback()
Me.Trans = Me.Conn.BeginTransaction
End Sub
Public Sub CloseDB()
Me.Conn.Close()
Me.Conn.Dispose()
Me.Trans.Dispose()
End Sub
Public Function ReadData(ByVal sql As String, ByVal ParamArray Obj() As Object)
' command Object
Dim CMD As New OleDbCommand(sql, Me.Conn, Me.Trans)
'add the parameters to the sql command
Dim I As Integer
For I = 0 To Obj.Length - 1
CMD.Parameters.AddWithValue("#" & I, Obj(I))
Next
Dim R = CMD.ExecuteReader()
'Do While R.Read
'Loop
Return R
End Function
End Class
Here is the Sub I use to fetch Data:
Dim connection As String = txt_util.readFromTextFile("ConnStr_2.txt", 0) + "Billing.mdb"
'connection string is in a text file with text at line 0 as "C:\BILLSERV\"
Private Sub searchAccnt(ByVal SIN As String)
'clear other fields
Clear("Acct")
Try
AccntDetail.DBConnect("ConcessionairesAccnt")
'Dim RS = AccntDetail.ReadData("Select * From AllAccounts Where SIN=#0", txtSIN.Text.Trim)
Dim RS = AccntDetail.ReadData("Select * From viewCSFAccnt Where SIN=#0", SIN)
RS.Read()
If RS.Hasrows = 0 Then
MsgBox("Accounts not found. Check the SIN you Enter.", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "Records not found.")
'txtAppNo.Focus()
Exit Sub
Else
'MsgBox("Accounts correct.", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "Records found.")
txtZoneNo.Text = RS.Item("Zone").ToString
txtSeq.Text = RS.Item("SeqNo").ToString
txtAccntName.Text = RS.Item("AccountName").ToString
txtAccntAddress.Text = RS.Item("HouseNo").ToString + " " + RS.Item("BLDGName").ToString + " " + RS.Item("Street").ToString + _
" " + RS.Item("BRGY").ToString
txtMeterNo.Text = RS.Item("MeterNo").ToString
txtAccntStatus.Text = varA.AccntStatus(RS.Item("Status").ToString)
'Dim con = AccessAccnt.DBConnect(connection, "")
'If con <> "Ok" Then
' MsgBox("Cannot establish a Connection to the server.", MsgBoxStyle.Critical, "Connection Lost...")
'End If
Dim ZoneNo = "Z" + GetChar(txtZoneNo.Text, 1) + GetChar(txtZoneNo.Text, 2) + "B" + GetChar(txtZoneNo.Text, 3) + GetChar(txtZoneNo.Text, 4)
AccessAccnt.DBConnect(connection, "")
Dim Acc = AccessAccnt.ReadData("SELECT * FROM " & ZoneNo & " WHERE AcctNo3=#1", txtSeq.Text)
Acc.Read()
txtLastReading.Text = Acc.Item("LastReading").ToString
Acc.close()
AccessAccnt.CloseDB()
End If
RS.Dispose()
AccntDetail.CloseDB()
dbCounter.DBConnect("ConcessionairesAccnt")
Dim result = dbCounter.ReadData("Select Top 1 CSFNo From CSFMaster WHERE (CSFNo LIKE '%" & ctrDate() & "%') order by CSFNo Desc")
result.read()
If result.hasrows = 0 Then
txtTrackingNo.Text = ctrDate() & "-" & "000001"
Else
txtTrackingNo.Text = counter.CtrLastItemWithChar("ConcessionairesAccnt", "CSFNo", "CSFMaster", "WHERE (CSFNo LIKE '%" & ctrDate() & "%') ORDER BY CSFNo DESC", 5)
End If
dbCounter.CloseDB()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
The Error is thrown here:
Dim Acc = AccessAccnt.ReadData("SELECT * FROM " & ZoneNo & " WHERE AcctNo3=#1", txtSeq.Text)
It Says:
System.InvalidOperationException: ExecuteReader requires an open and available connection. The connection's current state is closed.
The Other Parts of the Sub Works fine, The part where I fetch Data on my MSSQL Server database. The Problem lies in the Access data-Fetching Code.
I tried Using the code on another project (just the code where i fetch access data) I worked on other solutions. But I copy and paste my code on any form in this solution I keeps giving the Error.
I thought Maybe I closed the connection somewhere but this is the only instance I used this code in this entire project. (Just to get the last reading record.)
The Database is in the correct place (C:\BILLSERV)
I've Tried searching it here on SE but all I can see where suggestions about maybe forgetting to open the connection. I used this code before and this code works on my other solutions. I just cant seem to have it work here on this particular project. I wonder Why..
I tried running another project using this code and it works fine.
Is there a bug about Access connection on VB.net 2012, I have been using this code (DBConnForAccess Class) for about a year now and this is the first time I have encountered this error. btw I use Access 2003 because this database used to be for an old system created in VB6.
Lastly could this be because the solution came from another computer using a VB.Net Program same as mine. Because We work as a team here. Hope someone with a better knowledge on these systems could help. Thanks in advance.
EDIT
If a connection has been made, there should be a .ldb file in access which should appear. (I tested this on another project and an ldb file appear once a connection has been made, as we all know ldb file contains the data of the user using the db file.) I tried to re-run the system and while I'm using the system no ldb file was created.
Also,I thought Maybe I closed the connection somewhere but this is the only instance I opened a connection in access and which I used the code in this entire project. (Just to get the last reading record.)
So this is NOT a duplicate of “There is already an open DataReader…” Reuse or Dispose DB Connections? Just for clarifications
After a week of debugging and reading articles in the web.
We have found the culprit of the Error.
Seems that the Target CPU Option in Advance compiler Settings was change to AnuCPU.
We noticed this after we checked the other application projects we used.
Changing it Back to x86 solves the connection problem.
I wonder why this affected the connection to the access.
All is working fine now. thank you Plutonix and Steve for all your suggestions we'll be having a change in our codes.

VB Access Update data type mismatch

Sorry in advance, Im new to vb,
Im creating a small application for assignment as a MCQ quiz, Im using the same form but use the function of [nextques] proceed to next question and use [answer] to update the user answer to database(access).
I previously uses SQL Server and it work good but due to i need to run the application in school's computer where they wont allow me to install anything, I have no idea at all then decided to use access as it is easier to export and include it in debug file.
Ive go through some topics as well as did some changes however the problem persist. I set the [input] in access as integer, i did put parameter on it but it still not working.
ERROR code : Data type mismatch in criteria expression
Public Function answer(ans As Integer)
Try
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=mom.mdb;"
con.Open()
cmd.Connection = con
' Update the answer 1234 (as abcd) according to id in lblnum.text
Dim updatecmd As String = "UPDATE question SET [input] = #ans WHERE id = '" & lblnum.Text & "'"
cmd.Parameters.AddWithValue("#ans", ans)
cmd.CommandText = updatecmd
updatecmd = cmd.ExecuteNonQuery()
con.Close()
'Proceed to next question by calling Function NextQues
nextques()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return 0
End Function
I tried also to make it like this however another error shows: COM object that has been separated from its underlying RCW cannot be used
Public Function answer(ans As Integer)
Dim countid As Integer = 1
Try
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=mom.mdb;"
con.Open()
cmd.Connection = con
Dim updatecmd As String = "UPDATE question SET [input] = #ans WHERE id = #countid"
cmd.Parameters.AddWithValue("#countid", countid)
cmd.Parameters.AddWithValue("#ans", ans)
cmd.CommandText = updatecmd
updatecmd = cmd.ExecuteNonQuery()
countid = countid + 1
con.Close()
'Proceed to next question by calling Function NextQues
nextques()
Catch ex As Exception
MsgBox(ex.Message)
End Try
Return 0
End Function
change this line
Dim updatecmd As String = "UPDATE question SET [input] = #ans WHERE id = '" & lblnum.Text & "'"
to
Dim updatecmd As String = "UPDATE question SET [input] = #ans WHERE id = " & lblnum.Text

"Could not find installable ISAM" error in VB.NET

Im new to visual basic.. I would like to ask on how to fixed the problem "Could not find installable ISAM.". I used Visual Basic as programming language. I used MS access as the database. My program is to fetch data from access. This would be my code.
Imports System.Data.OleDb
Module Main
Dim mDataPath As String
Sub Main()
GetPupils()
Console.ReadLine()
End Sub
Private Function GetConnection() As OleDb.OleDbConnection
'return a new connection to the database5
Return New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Database Password=oNer00FooR3n0 " & "Data Source=" & "C:\Users\ERICO YAN\Desktop\MSaccessDB\MSaccessDB\oneroofccp.mdb")
End Function
Public Function GetPupils() As DataSet
Dim conn As OleDb.OleDbConnection = GetConnection()
Try
Dim ds As New DataSet 'temporary storage
Dim sql As String = "select * from SESSIONS" 'query
Dim da As OleDb.OleDbDataAdapter = New OleDb.OleDbDataAdapter(sql, conn) 'connection
Try
da.Fill(ds, "SESSIONS") 'fetch data from db
Finally
da.Dispose() 'in case something goes wrong
End Try
Dim startVal = 0 'first record
Dim endVal = ds.Tables(0).Rows.Count 'total number records
For var = startVal To endVal - 1 'display records
Console.WriteLine(ds.Tables(0).Rows(var).Item(0).ToString() + " " + ds.Tables(0).Rows(var).Item(1).ToString() + " " + ds.Tables(0).Rows(var).Item(3).ToString() + " " + ds.Tables(0).Rows(var).Item(3).ToString()) 'code for display id and name
Next
Return ds
Finally
conn.Close()
conn.Dispose()
End Try
End Function
End Module
I would like to know what is the cause of the error so that I can proceed to my program.. Thank you so much for the feedback..
You seem to be missing a delimiter after your password attribute.
I think you also need to use Jet OLEDB:Database Password=... instead (if indeed you have an access database protected with a password):
"Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Data Source=" & "C:\Users\ERICO YAN\Desktop\MSaccessDB\MSaccessDB\oneroofccp.mdb;" _
& "Jet OLEDB:Database Password=oNer00FooR3n0;"
Missing ; delimiter here:
...Password=oNer00FooR3n0 " & "Data Sourc...
Needs to be
...Password=oNer00FooR3n0 " & ";Data Sourc...
Also just Password instead of Database Password.
Initially, i too got this sort of error, but when i wrote the connection string in a single line (i mean without using [& _] or breaking in 2 lines, then this worked properly.
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\USER1\Desktop\MSaccessDB\MSaccessDB\my_database_file.mdb;Database Password=MyPassword"
Hope this helps.
Mukesh L.

Inserting variables into a query string - it won't work!

Basically i have a query string that when i hardcode in the catalogue value its fine. when I try adding it via a variable it just doesn't pick it up.
This works:
Dim WaspConnection As New SqlConnection("Data Source=JURA;Initial Catalog=WaspTrackAsset_NROI;User id=" & ConfigurationManager.AppSettings("WASPDBUserName") & ";Password='" & ConfigurationManager.AppSettings("WASPDBPassword").ToString & "';")
This doesn't:
Public Sub GetWASPAcr()
connection.Open()
Dim dt As New DataTable()
Dim username As String = HttpContext.Current.User.Identity.Name
Dim sqlCmd As New SqlCommand("SELECT WASPDatabase FROM dbo.aspnet_Users WHERE UserName = '" & username & "'", connection)
Dim sqlDa As New SqlDataAdapter(sqlCmd)
sqlDa.Fill(dt)
If dt.Rows.Count > 0 Then
For i As Integer = 0 To dt.Rows.Count - 1
If dt.Rows(i)("WASPDatabase") Is DBNull.Value Then
WASP = ""
Else
WASP = "WaspTrackAsset_" + dt.Rows(i)("WASPDatabase")
End If
Next
End If
connection.Close()
End Sub
Dim WaspConnection As New SqlConnection("Data Source=JURA;Initial Catalog=" & WASP & ";User id=" & ConfigurationManager.AppSettings("WASPDBUserName") & ";Password='" & ConfigurationManager.AppSettings("WASPDBPassword").ToString & "';")
When I debug the catalog is empty in the query string but the WASP variable holds the value "WaspTrackAsset_NROI"
Any idea's why?
Cheers,
jonesy
alt text http://www.freeimagehosting.net/uploads/ba8edc26a1.png
I can see a few problems.
You are using concatenation in a SQL statement. This is a bad practice. Use a parameterized query instead.
You are surrounding the password with single quotes. They are not needed and in fact, I'm surprised it even works assuming the password itself does not have single quotes.
You should surround classes that implement IDisposable with a Using block
You should recreate the WASP connection object in GetWASPcr like so:
Public Sub GetWASPAcr()
Dim username As String = HttpContext.Current.User.Identity.Name
Dim listOfDatabaseConnectionString As String = "..."
Using listOfDatabaseConnection As SqlConnection( listOfDatabaseConnectionString )
Using cmd As New SqlCommand("SELECT WASPDatabase FROM dbo.aspnet_Users WHERE UserName = #Username")
cmd.Parameters.AddWithValue( "#Username", username )
Dim dt As New DataTable()
Using da As New SqlDataAdapter( cmd )
da.Fill( dt )
If dt.Rows.Count = 0 Then
WaspConnection = Null
Else
Dim connString As String = String.Format("Data Source=JURA;Initial Catalog={0};User Id={1};Password={2};" _
, dt.Rows(0)("WASPDatabase") _
, ConfigurationManager.AppSettings("WASPDBUserName") _
, ConfigurationManager.AppSettings("WASPDBPassword"))
WaspConnection = New SqlConnection(connString);
End If
End Using
End Using
End Using
End Sub
In this example, listOfDatabaseConnectionString is the initial connection string to the central database where it can find the catalog name that should be used for subsequent connections.
All that said, why would you need a class level variable to hold a connection? You should make all your database calls open a connection, do a sql statement, close the connection. So, five database calls would open and close a connection five times. This sounds expensive except that .NET gives you connection pooling so when you finish with a connection and another is requested to be opened, it will pull it from the pool.
Your string passed into the constructor for this SqlConnection object will be evaluated when the class is instantiated. Your WASP variable (I'm assuming) won't be set until the method you have shown is called.
Might want to quit looking one you have found your database:
For i As Integer = 0 To dt.Rows.Count - 1
If dt.Rows(i)("WASPDatabase") Is DBNull.Value Then
WASP = ""
Else
WASP = "WaspTrackAsset_" + dt.Rows(i)("WASPDatabase")
break
End If
Next
[link text][1]You are building your string on the fly by adding the value of a column to a string. So, for the row in question for the column "WASPDatabase" was tacked on to your string. So you got what it had. On another note, your earlier query of "select ... from ... where ..." where you are manually concatinating the string of a variable makes you WIDE OPEN to SQL-Injection attacks.
Although this link [1]: how to update a table using oledb parameters? "Sample query using parameterization" is to a C# sample of querying with parameterized values, the similar principles apply to most all SQL databases.
At the time you're creating the new connection, WASP is holding the value you want it to be holding? It is a string data type? Try adding .ToString after WASP and see if that helps anything.
Interesting problem. =-)
The problem is, as Paddy already points out, that the WaspConnection object gets initialized before you even have the chance to call GetWASPAcr. Try this:
Public Sub GetWASPAcr()
'[...]
End Sub
Dim _waspConnection As SqlConnection
Public Readonly Property WaspConnection As SqlConnection
Get
If _waspConnection Is Nothing Then
GetWASPAcr()
_waspConnection = New SqlConnection("Data Source=JURA;Initial Catalog=" & WASP & ";User id=" & ConfigurationManager.AppSettings("WASPDBUserName") & ";Password='" & ConfigurationManager.AppSettings("WASPDBPassword").ToString & "';")
End If
Return _waspConnection
End Get
End Property