Database only adds (x) amount of rows before error system resources exceeded - database

I am having a problem with my code where i am only able to add so many lines of text before i get an error "system resources exceeded".
This is my code:
Dim x As Integer = MsgBox("Update Record?", MsgBoxStyle.YesNo, "Are you sure?")
If x = MsgBoxResult.Yes Then
Dim accessconn As New _
System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & "MyDB.accdb")
Dim com As System.Data.OleDb.OleDbCommand
accessconn.Close()
Try
For Each strLine As String In TextBox1.Text.Split(vbNewLine)
accessconn.Open()
Dim str As String
Dim dr As OleDbDataReader
str = "SELECT * FROM Table4 WHERE MD5='" & strLine & "'"
Dim cmd As OleDbCommand = New OleDbCommand(str, accessconn)
dr = cmd.ExecuteReader
If dr.Read() Then
Label2.Text = Label2.Text + 1
Else
accessconn.Open()
com = New System.Data.OleDb.OleDbCommand("INSERT INTO Table4(MD5) VALUES('" & strLine & "')", accessconn)
com.ExecuteReader(CommandBehavior.CloseConnection)
Label3.Text = Label3.Text + 1
com.Dispose()
accessconn.Close()
End If
Next
accessconn.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
MsgBox("Done")
PopulateGridview4()
End If
I would like to be able to add unlimited rows of text to the database if possible. Please Help.

You should change your code to something like the following. Note that
Everything that returns an object like OleDbConnection, OleDbCommand, or OleDbDataReader is wrapped in a Using block. These objects all implement the IDisposable interface, which means they should be cleaned up as soon as you're done with them.
Also note that your INSERT did not return any data, so you should use ExecuteNonQuery instead of ExecuteReader.
Finally, please don't get into the habit of putting Try/Catch/End Try blocks around everything. You were displaying the exception (you displayed ex.ToString, which is a good thing), but you then ignored the exception. As a good general rule, don't catch exceptions unless you can fix them.
Code:
Dim x As Integer = MsgBox("Update Record?", MsgBoxStyle.YesNo, "Are you sure?")
If x = MsgBoxResult.Yes Then
Using accessconn As New _
System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & "MyDB.accdb")
accessconn.Open()
For Each strLine As String In TextBox1.Text.Split(vbNewLine)
Dim str As String = "SELECT * FROM Table4 WHERE MD5='" & strLine & "'"
Using cmd As OleDbCommand = New OleDbCommand(str, accessconn)
Using dr As OleDbDataReader = cmd.ExecuteReader
If dr.Read() Then
Label2.Text = Label2.Text + 1
Else
Using com As OleDbCommand = New System.Data.OleDb.OleDbCommand("INSERT INTO Table4(MD5) VALUES('" & strLine & "')", accessconn)
com.ExecuteNonQuery()
End Using
Label3.Text = Label3.Text + 1
End If
End Using
End Using
Next
MsgBox("Done")
PopulateGridview4()
End Using
End If
P.S. you could probably have made this a little less indented by using If x <> MsgBoxResult.Yes Then get out, but I don't know if this is inside of a Sub or Function, so "get out" could be different.

Related

How to resolve : 'There is already an open DataReader associated with this Command which must be closed first.'

I've been trying to insert data into my sql database but this problem always show up
i've tried redoing it again and the same problem occurs and i'm really stumped right now
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim conn As SqlConnection = New SqlConnection("Data Source=DESKTOP-OBQR58O\SQLEXPRESS;Initial Catalog=Accounts;Integrated Security=True")
Dim comm As SqlCommand = New SqlCommand("insert into User(username, password)values('" + TextBox1.Text + "', '" + TextBox3.Text + "')", conn)
Dim data As SqlDataAdapter = New SqlDataAdapter(comm)
Dim user = TextBox1.Text
Dim pass = TextBox2.Text
Dim cpass = TextBox3.Text
Dim reader As SqlDataReader
conn.Open()
Dim cmd As SqlCommand = New SqlCommand("select Username from [User] where Username ='" + TextBox1.Text + "'", conn)
conn.Close()
conn.Open()
reader = cmd.ExecuteReader
If user.Trim() = "" Or pass.Trim() = "" Or cpass.Trim() = "" Then
MessageBox.Show("Empty Fields", "Blank Spaces")
ElseIf Not String.Equals(pass, cpass) Then
MessageBox.Show("Passwords do not match", "ERROR")
conn.Close()
ElseIf reader.HasRows Then
MessageBox.Show("Username already exists!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning)
TextBox1.Clear()
conn.Close()
reader.Close()
Else
MessageBox.Show("Account created succesfully!", "Success")
Dim table As DataTable = New DataTable()
data.Fill(table) ' this is where the problem occurs.
TextBox1.Clear()
TextBox2.Clear()
TextBox3.Clear()
Dim log As New Login
Me.Close()
log.Show()
conn.Close()
End If
conn.Close()
End Sub
I honestly don't know what to do
You open your reader up at the top:
reader = cmd.ExecuteReader
So, it's open. And then, when you run the Fill command, it conflicts with the open reader!
The simplest fix - although, personally, I would restructure the code a bit, to bring the OpenReader nearer to where it is used - would be to add a Close to your reader right before the Fill.
Else
reader.Close() ' what you would add
MessageBox.Show("Account created succesfully!", "Success")
Dim table As DataTable = New DataTable()
data.Fill(table) ' this is where the problem occurs.
VERY IMPORTANT: If you're not familiar with the concept of "SQL Injection Attacks", read up on them, right away. You should NEVER execute SQL that's been built by constructing a string with unvalidated data from the user. You should pass parameters instead.
After all, what if I typed in the user name of "Irrelevant';DROP TABLE Users;--"? You'd wind up with a SQL Statement that contained "SELECT Username from [Users] WHERE [Username] = 'Irrelevant'; DROP TABLE Users; --'"
And, of course, you should validate the input as well, for things like embedded HTML and script! But that's more complicated than just using SQL Parameters.

“Not allowed to change the 'ConnectionString' property.” error

While i was adding data to access database, i got error:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
TB2.Clear()
NameofG.Clear()
NunberofG.Clear()
UnitofG.Clear()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
pro = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Piyawat\Desktop\PPCC\Stock.accdb;"
connstring = pro
myconnection.ConnectionString = connstring
If myconnection.State = ConnectionState.Closed Then
myconnection.Open()
End If
command = "insert into Stock([InvoiceID],[Type],[Item],[Amout],[Unit]) Value ('" & TB2.Text & "','" & CB1.Text & "','" & NameofG.Text & "','" & NunberofG.Text & "','" & UnitofG.Text & "')"
Dim cmd As OleDbCommand = New OleDbCommand(command, myconnection)
cmd.Parameters.Add(New OleDbParameter("InvoiceID", CType(TB2.Text, String)))
cmd.Parameters.Add(New OleDbParameter("Type", CType(CB1.Text, String)))
cmd.Parameters.Add(New OleDbParameter("Item", CType(NameofG.Text, String)))
cmd.Parameters.Add(New OleDbParameter("Amout", CType(NunberofG.Text, String)))
cmd.Parameters.Add(New OleDbParameter("Unit", CType(UnitofG.Text, String)))
MsgBox("Record Save")
Try
cmd.ExecuteNonQuery()
cmd.Dispose()
TB2.Clear()
CB1.Text.DefaultIfEmpty
NameofG.Clear()
NunberofG.Clear()
UnitofG.Clear()
Catch ex As Exception
MsgBox("Mistake")
End Try
End Sub
How to fix the error? Please help. Thanks
I would AWAYS ensure that after you use the connection, you close it.
however, you can get .net to automatics do this for you.
Also, go into project->settings and add your connection string there - that way you NEVER have to place or have connection strings in code - (bad idea).
Hence, your code should and would look like this:
Dim strSQL As String = "INSERT INTO Stock([InvoiceID],[Type],[Item],[Amout],[Unit]) " &
"VALUES (#TB2, #CB1, #NameofG, #NunberofG, #UnitofG)"
Using cmd As New OleDbCommand(strSQL, New OleDbConnection(My.Settings.Test44))
cmd.Parameters.Add("#TB2", OleDbType.VarWChar).Value = TB2.Text
cmd.Parameters.Add("#CB1", OleDbType.VarWChar).Value = CB1.Text
cmd.Parameters.Add("NameofG", OleDbType.VarWChar).Value = NameofG.Text
cmd.Parameters.Add("#NumberofG", OleDbType.Integer).Value = NunberofG.Text
cmd.Parameters.Add("#UnitofG", OleDbType.Integer).Value = UnitOfG.Text
cmd.Connection.Open()
Try
cmd.ExecuteNonQuery()
MsgBox("Record Save")
Catch ex As Exception
MsgBox("Error = " & ex.Message)
End Try
End Using
note the following:
No messy string concentation.
No messy quotes for strings, non quotes for numbers.
clean easy to read.
use parmaters - safe.
And with a using block, we do NOT have to dispose or close the conneciton - it is automatic for you. So ALWAYS assume it is closed.
note how we don't have a seperate conneciton object - don't need one.
note how the command object is REALLY nice.
The command object has:
a connection object - you don't need to create a new one
command text
a reader!!! - you can use command object - no need to load + create a reader
I moved the database code to a separate method.
Starting with the user interface code, you first want to validate the input. I had to guess at the datatypes because your code made them all look like strings. I hope this is not true.
It seems you got mixed up with Parameters. I am very glad that you tried to used them but they don't appear in your sql string so they are not being used. You don't want to concatenate strings with user input because it risks sql injection.
The # sign preceding the parameter names is just a convention that makes it easy to recognize.
You need to keep database objects local to the method where they are used. That way they can be closed and disposed with Using...End Using blocks as quickly as possible.
Private ConStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Piyawat\Desktop\PPCC\Stock.accdb;" '"Your connection string"
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'Validate input
Dim ID As Integer
Dim Amt As Decimal
Dim Unt As Integer
Dim message = "Please enter a number for the"
If Not Integer.TryParse(TB2.Text, ID) Then
MessageBox.Show(message & " Invoice ID.")
Return
End If
If Not Decimal.TryParse(NunberofG.Text, Amt) Then
MessageBox.Show(message & " Amount.")
Return
End If
If Not Integer.TryParse(UnitofG.Text, Unt) Then
MessageBox.Show(message & " Unit")
Return
End If
'Call the insert method
Try
InsertInvoice(ID, CB1.Text, NameofG.Text, Amt, )
Catch ex As Exception
MsgBox(ex.Message)
Return
End Try
MessageBox.Show("Record Saved")
TB2.Clear()
CB1.Text.DefaultIfEmpty
NameofG.Clear()
NunberofG.Clear()
UnitofG.Clear()
End Sub
Private Sub InsertInvoice(InvoiceID As Integer, Type As String, Item As String, Amount As Decimal, Unit As Integer)
Dim Command = "insert into Stock([InvoiceID],[Type],[Item],[Amout],[Unit]) Value (#InvoiceID,#Type,#Item,#Amount,#Unit)"
Using myconnection As New OleDbConnection(ConStr),
cmd As New OleDbCommand(Command, myconnection)
With cmd.Parameters
.Add("#InvoiceID", OleDbType.Integer).Value = InvoiceID
.Add("#Type", OleDbType.VarChar).Value = Type
.Add("#Item", OleDbType.VarChar).Value = Item
.Add("#Amout", OleDbType.Decimal).Value = Amount
.Add("#Unit", OleDbType.Integer).Value = Unit
End With
End Using
End Sub

Search function using listview in vb

i get a change of data in a first column in a listview after search a data.
Example:
in a first column, the data must display a room code like "3234" but after do a searching the data change to "Room_Code".
Below is the code for search function
Private Sub Search()
ListViewRoom.Items.Clear()
Dim item As New ListViewItem
Dim _isFound As Boolean = False
Dim colName() As String = {"Room_Code", "Room_Type", "Room_No", "Room_Price", "Room_Status", "No_of_Occupancy"}
Dim strSqlSearch As String = "SELECT Room_Code, Room_Type, Room_No, Room_Price, Room_Status, No_of_Occupancy " & _
"FROM Room " & _
"WHERE " & colName(cboSearch.SelectedIndex) & " LIKE '%" & txtSearch.Text & "%'"
dbSource = "Data Source=LAILATUL-PC\SERVER;Initial Catalog=HotelManagementSystem;Integrated Security=True"
Using con As New SqlClient.SqlConnection("Data Source=LAILATUL-PC\SERVER;Initial Catalog=HotelManagementSystem;Integrated Security=True")
Using com As New SqlClient.SqlCommand()
With com
.Connection = con
.CommandType = CommandType.Text
.CommandText = strSqlSearch
End With
Try
con.Open()
Dim dr As SqlClient.SqlDataReader = com.ExecuteReader
While dr.Read
_isFound = True
item = ListViewRoom.Items.Add("Room_Code".ToString)
item.SubItems.Add(dr("Room_Type".ToString))
item.SubItems.Add(dr("Room_No".ToString))
item.SubItems.Add(dr("Room_Price".ToString))
item.SubItems.Add(dr("Room_Status".ToString))
item.SubItems.Add(dr("No_of_Occupancy".ToString))
End While
If Not _isFound Then
MsgBox("No results found.", MsgBoxStyle.OkOnly, "Information")
End If
Catch ex As Exception
MsgBox(ex.Message.ToString(), MsgBoxStyle.OkOnly, "Error")
End Try
End Using
End Using
Tq
Um, because you're telling it to:
item = ListViewRoom.Items.Add("Room_Code".ToString)
I suppose that that should be:
item = ListViewRoom.Items.Add(dr("Room_Code").ToString)
By the way, you've got several other pointless calls to ToString too, e.g.
item.SubItems.Add(dr("Room_Type".ToString))
What's the point of calling ToString on a literal? Surely it's the field value that you want converted to a String:
item.SubItems.Add(dr("Room_Type").ToString())
You really should be using a DataGridView and simply binding a DataTable instead of abusing a ListView, which is NOT a grid control.

How to return database fields from checkbox selection?

the code below returns the fields of a given table ("Employee"), but I need to return the fields of ALL the tables in the given database, is this possible? My assumption is a For loop which loops round the tables in the database and prints the corresponding fields but my efforts seem to be in vain
Public Sub getDbFields()
Dim i As Integer
Dim dbcon As New System.Data.OleDb.OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source = " & dblocation & _
"\" & dbname)
Try
dbcon.Open()
dbDt = dbcon.GetOleDbSchemaTable(OleDb.OleDbSchemaGuid.Columns, New Object() _
{Nothing, Nothing, "Employee", Nothing})
For i = 0 To dbDt.Rows.Count - 1
'compile lbtables with a list of available tables from the database
newLine()
frmMain.lstTables.Items.Add(dbDt.Rows(i)!COLUMN_NAME.ToString())
Next
Catch ex As Exception
MessageBox.Show(ex.Message.ToString(), "Data Load Error", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation)
End Try
End Sub
This routine will be fired from the selection of a checkbox
This will return all columns on a database
Using con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=" + dblocation + "\" + dbname)
con.Open()
Dim schema as DataTable = con.GetSchema("COLUMNS")
Dim dr as DataRow
For Each dr in schema.Rows
Dim tablename as string = dr("TABLE_NAME").ToString()
if Not tablename.StartsWith("MSys") then
Console.WriteLine(dr("TABLE_NAME").ToString() + " " + dr("COLUMN_NAME").ToString())
End if
Next
End Using
Please note that the bang (!) syntax is not allowed in vb.net.
Also your code could work if you change
dbDt = dbcon.GetOleDbSchemaTable(OleDb.OleDbSchemaGuid.Columns, New Object() _
{Nothing, Nothing, Nothing, Nothing})
and this line
frmMain.lstTables.Items.Add(dbDt.Rows(i)("COLUMN_NAME").ToString())

How to check if a record exists in an Access database

I'm trying a new approach for a project that I'm working on and I'm just starting to learn about Access Databases. I using VB.net and my question is: How do you see if a record exists in the table of the database. I thought I had it understood but that is not the case. I'm creating a login and I want it to check if the Username that they typed in exists before it tries to compare what you typed with what's in the database. I see alot of questions on how to do this...but not for VB.net and MS Access
Here's my code:
Imports System.Data.OleDb
Public Class LoginForm1
Dim provider As String
Dim dataFile As String
Dim connString As String
Public myConnection As OleDbConnection = New OleDbConnection
Public dr As OleDbDataReader
Dim Errors As String
Public Sub AccessAccountDatabase()
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source ="
dataFile = "C:\Users\Richard\Documents\Visual Studio 2010\Projects\CybSol Journal Database\CybSol Journal Database\cgi-bin\Data.mdb"
connString = provider & dataFile
myConnection.ConnectionString = connString
Errors = ""
Try
myConnection.Open()
Dim str As String
str = "SELECT * FROM Accounts WHERE Username='" & UsernameTxt.Text & "' AND Password='" & PasswordTxt.Text & "'"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
dr = cmd.ExecuteReader
dr.Read()
If UsernameTxt.Text = dr("Username").ToString AndAlso PasswordTxt.Text = dr("Password").ToString Then
Dim Welcome As String = "SELECT * FROM Accounts WHERE Real_Name=" & "Username"
MsgBox("Welcome back " & dr("Real_Name") & "!")
Else
MsgBox("Login Failure")
End If
myConnection.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub OkayBtn_Click(sender As System.Object, e As System.EventArgs) Handles OkayBtn.Click
AccessAccountDatabase()
End Sub
End Class
So now my question is... How do you get it to check if a record exists in the database, because when you type in the correct information (The correct username and password that exists in the database) it says welcome and all. But when you type in the wrong Username and/or Password it doesn't work. Without the "Try Catch" statement the program just freezes. With the try catch it states this:
System.InvalidOperationException: No data exists for the row/column.
at System.Data.OleDb.OleDbDataReader.DoValueCheck(Int32 ordinal)
at System.Data.OleDb.OleDbDataReader.GetValue(Int32 ordinal)
at System.Data.OleDb.OleDbDataReader.get_Item(String name)
at CybSol_Journal_Database.LoginForm1.AccessAccountDatabase() in c:\users\richard\documents\visual studio 2010\Projects\CybSol Journal Database\CybSol Journal Database\LoginForm1.vb:line 36
Addition information: line 36 is this: If UsernameTxt.Text = dr("Username").ToString AndAlso PasswordTxt.Text = dr("Password").ToString Then
First problem:
PASSWORD is a reserved keyword in Access. You should encapsulate in square brackets:
"SELECT * FROM Accounts WHERE Username='" & UsernameTxt.Text & _
"' AND [Password]='" & PasswordTxt.Text & "'"
Second problem:
NEVER use string concatenation to create sql text. ALWAYS use parameters
str = "SELECT * FROM Accounts WHERE Username=? AND [Password]=?"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
cmd.Parameters.AddWithValue("user", UserNameTxt.Text)
cmd.Parameters.AddWithValue("pass", PasswordTxt.Text)
dr = cmd.ExecuteReader
Why? look here what could happen if you concatenate strings from user input
Third problem: Test if your command returns rows
If dr.Read() Then
......
End if
I added some Using statements so you don't have to manually close the connections. Also, I parameterized the SQL statement to prevent SQL Injection.
Public Class LoginForm1
Dim provider As String
Dim dataFile As String
Dim connString As String
'Public myConnection As OleDbConnection = New OleDbConnection
'Public dr As OleDbDataReader
Dim Errors As String
Public Sub AccessAccountDatabase()
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source ="
dataFile = "C:\Users\Richard\Documents\Visual Studio 2010\Projects\CybSol Journal Database\CybSol Journal Database\cgi-bin\Data.mdb"
connString = provider & dataFile
myConnection.ConnectionString = connString
Errors = ""
Try
Using myConnection As OleDbConnection = New OleDbConnection(connString)
myConnection.Open()
Dim str As String
str = "SELECT * FROM Accounts WHERE Username=#USER AND [Password]=#PWD "
Using cmd As OleDbCommand = New OleDbCommand(str, myConnection)
cmd.Parameters.AddWithValue("#USER", UsernameTxt.Text)
cmd.Parameters.AddWithValue("#PWD", PasswordTxt.Text)
Using dr As OleDbDataReader = cmd.ExecuteReader
If dr.HasRows Then
dr.Read()
If UsernameTxt.Text = dr("Username").ToString AndAlso PasswordTxt.Text = dr("Password").ToString Then
Dim Welcome As String = "SELECT * FROM Accounts WHERE Real_Name=" & "Username"
MsgBox("Welcome back " & dr("Real_Name") & "!")
Else
MsgBox("Login Failure")
End If
Else
MsgBox("Login Failure")
End If
End Using
End Using
End Using
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Private Sub OkayBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OkayBtn.Click
AccessAccountDatabase()
End Sub
End Class
You're on the right track. The OleDbDataReader.Read returns a boolean indicating whether or not it successfully read an existing row. Therefore, you can check to see if it returned True before trying to read the record. For instance:
If dr.Read() Then
If UsernameTxt.Text = dr("Username").ToString AndAlso PasswordTxt.Text = dr("Password").ToString Then
Dim Welcome As String = "SELECT * FROM Accounts WHERE Real_Name=" & "Username"
MsgBox("Welcome back " & dr("Real_Name") & "!")
Else
MsgBox("Login Failure")
End If
End If
Also, I feel I should at least mention that storing a password in plain text is never a good idea.
You don't have to check for the username and password in your code again since if does not match in the database, no rows will be returned.
You can simply do
dr = cmd.ExecuteReader
If dr.HasRows Then
//it matched
Else
//it didn't match. could not log in
End If
Your approach is below if you still want to keep it but it's not necessary
dr = cmd.ExecuteReader
If dr.HasRows Then
dr.Read()
If UsernameTxt.Text = dr("Username").ToString AndAlso PasswordTxt.Text = dr("Password").ToString Then
Else
End If
End If
Use the Read() method on your DataReader (note that this keeps your connection to the database open and you'll be unable to execute any other commands on the database while your DataReader is still Reading.
If String.Compare(dr("Username").ToString(), UsernameTxt.Text, true) AndAlso String.Compare(dr("Password").ToString(), PasswordTxt.Text.ToString() Then
' The username and password for the record match
' the input from the login form
ProcessLogin()
Else
' Invalid username or password, send an error
End If

Resources