I wrote this code to write my data into a database
Public Class SQL_Client
Sub AddData(ByRef myGDI As GeneralInfo)
Dim conStr As String = "Server=NB01009;Database=DEV_DW;Trusted_Connection=true"
Dim query As String = String.Empty
query = "INSERT INTO GeneralInfo(id, name, data) VALUES (#id, #name, #data)"
Using con As SqlConnection = New SqlConnection(conStr)
Using comm As New SqlCommand
With comm
.Connection = con
.CommandType = CommandType.Text
.CommandText = query
.Parameters.AddWithValue("#id", myGDI.id)
.Parameters.AddWithValue("#name", myGDI.name)
.Parameters.AddWithValue("#data", "Hallo Data")
End With
Try
con.Open()
comm.ExecuteNonQuery()
Catch ex As SqlException
Console.WriteLine(ex.Message.ToString(), "Error Message")
End Try
End Using
Dim subquery As String = String.Empty
query = "INSERT INTO FullData(GeneralInfoID, userRunID VALUES(#GeneralInfoID, #userRunID)"
For Each myData As FullData In myGDI.data
Using command As New SqlCommand
With command
.Connection = con
.CommandType = CommandType.Text
.CommandText = query
.Parameters.AddWithValue("#GeneralInfoID", myGDI.id)
.Parameters.AddWithValue("#userRunID", myData.userRunID)
End With
Try
con.Open()
command.ExecuteNonQuery()
Catch ex As SqlException
Console.WriteLine(ex.Message.ToString(), "Error Message")
End Try
End Using
Next
End Using
End Sub
End Class
Since I have a nested object I want to write into the database (see here) I use a loop and a seconed Using Statement. At the second command.ExecuteNonQuery() it get the undhandled Exception:
System.INvalidOperationException: 'The connection was not closed. The connection's current state is open.'
I actually thought that after leaving the Using statement the connection would be closed automatically. But it looks like this assumption was wrong. Could anyone tell me how to handle this correctly?
You're opening the connection twice before the connection is closed.
It will automatically be closed after the last End Using.
Remove the second con.Open() and it should be fine.
Related
I'm trying to delete an entry from my database. But when the ExecuteNonQuery has to do it's job it can't find the enabled connection and give me this error :
System.InvalidOperationException :'ExecuteNonQuery : connection property has not been initialized'
Here is what I did :
Dim delete As New OleDbCommand
Dim da As OleDbDataAdapter
Dim ds As DataSet
Dim dt As DataTable
initConnectionDtb(pathDtb)
openConnection()
If TextBox2.Text <> "" Then
delete.CommandText = "delete FROM USERS WHERE NAME = '" & TextBox2.Text & "'"
delete.CommandType = CommandType.Text
delete.ExecuteNonQuery()
MsgBox("USER HAS BEEN DELETED")
Else
MsgBox("ERROR")
End If
I could check if it was properly connected to the Database thanks to connectionName.State
I also enterily rewrote the connetion to the database in the function but ExecuteNonQuery still couldn't connect even though the connection was opened
I saw that i'm not the only one on this website but none of the previous answers have helped me.
#Filburt pointed out, how are you assigning your connection to your command object. Here is an example :
Using connection As OleDbConnection = New OleDbConnection(connectionString)
connection.Open()
Dim command As OleDbCommand = New OleDbCommand(queryString, connection)
command.ExecuteNonQuery()
End Using
In your code, you need to assign the connection object to your command object. We can't see what code you have in initConnectionDtb(pathDtb) or openConnection()
To adapt this to your code:
delete.Connection = <<your connection object here>>
delete.CommandText = "delete FROM USERS WHERE NAME = '" & TextBox2.Text & "'"
delete.CommandType = CommandType.Text
delete.ExecuteNonQuery()
Another note: look into parameterizing your query strings instead of hand stringing the values. This will prevent issues with TextBox2.Text having a value like O'Toole which will cause a syntax error as well as SQL Injection.
Here's what i used to initialize my connection :
Public Function initConnectionDtb(ByVal path As String) As Boolean
initConnectionDtb = True
Connection = New OleDbConnection
Try
Connection.ConnectionString = "provider=microsoft.jet.oledb.4.0;" & "data source= " & path & ";"
Catch ex As Exception
Return False
End Try
End Function
Public Function openConnection() As Boolean
openConnection = True
Try
Connection.Open()
MsgBox(Connection.State) 'to test if my connection really openned in my previous post
Catch ex As Exception
MsgBox(ex.Message)
Return False
End Try
End Function
Public Sub closeConnection()
If Not IsNothing(Connection) Then
If Connection.State = ConnectionState.Open Then
Connection.Close()
End If
MsgBox(Connection.State)
Connection.Dispose()
Connection = Nothing
End If
End Sub
So far it worked for everything i tried (adding someone to the database for exemple)
I want to Insert 2 different data in 2 different table of ms-access.
And it shows this error.
I have a code like this:
try
dim sql1,sql2 as string
sql1 = "INSERT INTO table1(something)VALUES(something)"
cmd = new oledbcommand(sql1, connection)
cmd.executenoquery()
sql2 = "INSERT INTO table2(something)VALUES(something)"
cmd2 = new oledbcommand(sql2, connection)
cmd2.executenoquery()
catch ex as exception
msgbox(ex.tostring())
(where these cmd1,cmd2 are defined in controlModule.)
so,what should I do ?
Any help is appreciated. Thank You
I think closing the connection fixes the issue, best by using the Using-statement:
try
Using con As OleDbConnection = GetConnection() ' or New OlebConnection(...)
Using cmd = con.CreateCommand()
cmd.CommandText = "INSERT INTO table1(something)VALUES(#something)"
cmd.Parameters.AddWithValue("#something", something)
con.Open()
cmd.ExecuteNonQuery()
End Using
End Using
Using con As OleDbConnection = GetConnection()
Using cmd = con.CreateCommand()
cmd.CommandText = "INSERT INTO table2(something)VALUES(#something)"
cmd.Parameters.AddWithValue("#something", something)
con.Open()
cmd.ExecuteNonQuery()
End Using
End Using
Catch ex As Exception
msgbox(ex.tostring())
End Try
This is a concurrency issue. Because some other part of your code or MS Access itself accesses the database at the same time.
The fact is that you're not closing the connection after it's use. So the 2nd call should fail with that exception. Instead, you should wrap your disposables - e.g. the OleDbConnection, commands, etc. - in a using statement. That way, the connection will be closed, even if an exception occur:
Using con As New OleDbConnection, cmd1 As OleDbCommand = con.CreateCommand, cmd2 As OleDbCommand = con.CreateCommand()
cmd1.CommandText = "INSERT INTO table1(something)VALUES(something)"
cmd1.ExecuteNonQuery()
cmd2.CommandText = "INSERT INTO table2(something)VALUES(something)"
cmd2.ExecuteNonQuery()
End Using
Private Sub btnUpdate_Click(sender As Object, e As EventArgs) Handles btnUpdate.Click
Try
Dim con As New SqlConnection
Dim cmd As New SqlCommand
con.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\Comp-296\Project1\Project1\Game_time.mdb"
con.Open()
cmd.Connection = con
cmd.Connection = con
cmd.CommandText = ("UPDATE User_Name SET User_Name = #User_Name, Game_Name = #Game_Name, Score = #Score, Time/Date = #Time/Date")
cmd.Parameters.Add("#User_Name", SqlDbType.VarChar).Value = txtUser.Text
cmd.Parameters.Add("#Game_Name", SqlDbType.VarChar).Value = txtGame.Text
cmd.Parameters.Add("#Score", SqlDbType.VarChar).Value = txtScore.Text
cmd.Parameters.Add("#Time/Date", SqlDbType.DateTime).Value = txtDate.Text
cmd.ExecuteNonQuery()
MessageBox.Show("Data Update successfully")
con.Close()
Catch ex As System.Exception
MessageBox.Show("Data Update has failed")
End Try
End Sub
The code is giving an Exception is an ArgumentException and also :Keyword not supported: 'provider'.
You are using Access. This database cannot be opened using the classes in System.Data.SqlClient. These classes are used when you want to connect to Sql Server, Sql Server Express or LocalDB.
If you want to reach an MSAccess database you need the classes in System.Data.OleDb and these classes are OleDbConnection, OleDbCommand etc...
Said that, please note, that your field Date/Time will give you headaches. Change that name or put always square brackets around it because the / will be interpreted as the division operator
So your code could be:
Using con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\Comp-296\Project1\Project1\Game_time.mdb")
Using cmd = new OleDbCommand("UPDATE User_Name
SET User_Name = #User_Name,
Game_Name = #Game_Name,
Score = #Score, [Time/Date] = #dt", con)
con.Open()
cmd.Parameters.Add("#User_Name", OleDbType.VarWChar).Value = txtUser.Text
cmd.Parameters.Add("#Game_Name", OleDbType.VarWChar).Value = txtGame.Text
cmd.Parameters.Add("#Score", OleDbType.VarWChar).Value = txtScore.Text
cmd.Parameters.Add("#dt", OleDbType.Date).Value = Convert.ToDateTime(txtDate.Text)
cmd.ExecuteNonQuery()
MessageBox.Show("Data Update successfully")
End Using
End Using
Other notes:
Disposable objects like the connection and the command should be enclosed inside a Using Statement to be disposed and closed as soon as possible.
The time field requires a DateTime value not a string. If you pass a string you will face the automatic conversion made by the engine and sometime the engine is unable to produce a valid date from your input string. This will raise another exception (DataType mismatch). Better check and convert the value before passing it.
Also the type of the parameters should be from the OleDbType enum.
SELECT count(*) FROM table name
this above code work fine in standalone sql table, but who can I do this simple task with in vb.net wpf project ?
This is only a sample ..just check and try your own way.
Sample:
Dim connetionString As String
Dim connection As SqlConnection
Dim command As SqlCommand
Dim sql As String
connetionString = "Data Source=ServerName;Initial Catalog=DatabaseName;
User ID=UserName;Password=Password"
sql = "Select count(*) from table"
connection = New SqlConnection(connetionString)
Try
connection.Open()
command = New SqlCommand(sql, connection)
Dim sqlReader As SqlDataReader = command.ExecuteReader()
While sqlReader.Read()
MsgBox("Count =" & sqlReader.Item(0))
End While
sqlReader.Close()
command.Dispose()
connection.Close()
Catch ex As Exception
MsgBox("Can not open connection ! ")
End Try
If your query return more than one values you can use SqlDataReader(), but if you are sure your query will return only a single value you can use ExecuteScalar() and if your query wont return any result, eg:- insert.it will insert value not return any data so we can use ExecuteNonQuery().The ExecuteNonQuery() will return a result which indicate is it successful or failure. If you want you can assign the same else no need.
Use SqlCommand.ExecuteScalar() method to execute query that return singular/scalar value (example based on that link) :
Dim count As Integer
Dim connString = "connection string to your database here"
Using conn As New SqlConnection(connString)
Dim cmd As New SqlCommand("SELECT COUNT(*) FROM MyTable", conn)
Try
conn.Open()
count = Convert.ToInt32(cmd.ExecuteScalar())
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Using
I am trying to do an update query from a winform with two variables without using a dataset.
I assign both of my variable and then run the query but it keeps giving the error that zcomp is not a valid column name. Which of course is true but I tell it which column before I say = zcomp. Below is my code that is running the query.
Dim zamnt As Integer = WopartsDataGridView.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
Dim zcomp As Integer = gridRow.Cells(0).Value
Dim con As New SqlConnection
Dim cmd As New SqlCommand
Try
con.ConnectionString = "Data Source=MNT-MGR-2\SQLEX;Initial Catalog=MT;Integrated Security=True"
con.Open()
cmd.Connection = con
cmd.CommandText = "UPDATE dbo.sparts SET [dbo.sparts.QtyonHand] = [dbo.sparts.QtyonHand] - zamnt WHERE [ComponentID] = zcomp"
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Error while updating record on table..." & ex.Message, "Update Records")
Finally
con.Close()
gridRow.Cells(4).Value = "Yes"
End Try
I have tried it several different ways. It works just fine if I take out the zamnt and zcomp and put the actual number values that are in the variables. Please help I've been searching all day for a way to use the variables with this update query.
Thanks,
Stacy
You are probably looking for how to use parameters in ADO.NET. For your example, it can look like this:
cmd.Parameters.Add("#zamnt", zamnt);
cmd.Parameters.Add("#zcomp", zcomp);
Put these two lines anywhere before ExecuteNonQuery.
Because parameters need a # prefix, you would also need to change your query to say #zamnt instead of just zamnt, and same for zcomp:
cmd.CommandText = "UPDATE dbo.sparts SET [dbo.sparts.QtyonHand] = [dbo.sparts.QtyonHand] - #zamnt WHERE [ComponentID] = #zcomp"
In addition to using parameters, the "Using" statement closes the connection and disposes resources:
Dim zamnt As Integer = WopartsDataGridView.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
Dim zcomp As Integer = gridRow.Cells(0).Value
Try
Using con As New SqlConnection("Data Source=MNT-MGR-2\SQLEX;Initial Catalog=MT;Integrated Security=True")
con.Open()
Using cmd As New SqlCommand
cmd.CommandText = "UPDATE dbo.sparts SET [dbo.sparts.QtyonHand] = [dbo.sparts.QtyonHand] - #zamnt WHERE [ComponentID] = #zcomp"
cmd.Parameters.AddWithValue("#zamt", zamnt)
cmd.Parameters.AddWithValue("#zcomp", zcomp)
cmd.ExecuteNonQuery()
End Using
End Using
Catch ex As Exception
MessageBox.Show("Error while updating record on table..." & ex.Message, "Update Records")
Finally
con.Close()
gridRow.Cells(4).Value = "Yes"
End Try
have u tried this?
Dim zamnt As Integer = WopartsDataGridView.Rows(e.RowIndex).Cells(e.ColumnIndex).Value
Dim zcomp As Integer = gridRow.Cells(0).Value
Dim con As New SqlConnection
Dim cmd As New SqlCommand
Try
con.ConnectionString = "Data Source=MNT-MGR-2\SQLEX;Initial Catalog=MT;Integrated Security=True"
con.Open()
cmd.Connection = con
cmd.CommandText = "UPDATE dbo.sparts SET [dbo.sparts.QtyonHand] = [dbo.sparts.QtyonHand] -" + zamnt + " WHERE [ComponentID] =" + zcomp
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Error while updating record on table..." & ex.Message, "Update Records")
Finally
con.Close()
gridRow.Cells(4).Value = "Yes"
End Try