having this code (which i know the open/executenonquery/close conection in for loop is absolutely horrible).
Public Shared Sub salvarDatos(ByRef conexion As SqlConnection, ByRef datos As List(Of DatoBdReloj))
For i = 0 To datos.Count - 1
Dim laQuery As String = "Insert INTO MARCADASRELOJ (COD_MAR_RELOJ,FECHA_RELOJ,HORA_RELOJ,MINUTOS_RELOJ,NRO_RELOJ,NRO_TARJ) " & _
"VALUES (#codMarReloj,#fechaReloj,#horaReloj,#minutosReloj,#nroReloj,#nroTarj)"
Dim datoReloj As DatoBdReloj = datos.Item(i)
Dim command As SqlCommand = New SqlCommand(laQuery, conexion)
command.Parameters.AddWithValue("codMarReloj", datoReloj.tipoMarca)
command.Parameters.AddWithValue("fechaReloj", datoReloj.fechaHoraMarcaDT)
command.Parameters.AddWithValue("horaReloj", datoReloj.fechaHoraMarcaDT.Hour)
command.Parameters.AddWithValue("minutosReloj", datoReloj.fechaHoraMarcaDT.Minute)
command.Parameters.AddWithValue("nroReloj", datoReloj.idReloj)
command.Parameters.AddWithValue("nroTarj", datoReloj.idUsuario)
conexion.Open()
command.ExecuteNonQuery()
conexion.Close()
Next
End Sub
I don't have much experience with .net , but for what i have read using the AddWithValue method i can prevent sql injections and according to the "book" is the right way to do it (tell me if i'm wrong).
using a sentence like "Insert into xxx (x1,x2,x3) values ("val","val","val"),(...),(...)" to insert multiple rows is not an option for me because my database is running with sql 2005.
How can i take away that horrible open/execute/close inside the for loop to insert multiple rows no matter if it's sql 2005 or 2008 and also keep being secure from sql injections by using the AddWithValue Method?
Thanks! :)
Hello you can use bulkinsert
The code: BulkInserter
How to use it
Related
I have a list of Users Names in ComboBox and Some TextBoxes. When ComboBox text changes (i.e I select some username from ComboBox), The TextBoxes are filled with user details from the database.
I have code to achieve this in SQL Database. But these queries are not working with MsAccess database.
MysqlConn = New MySqlConnection
Mysql.ConnectionString = "server=localhost;user=root;password=root;database=database"
Dim READER As MySqlDataReader
Try
MysqlConn.open()
Dim Query As String
Query("select * from database.usernames where name='" & ComboBox1.Text & "'")
Command = New MySqlCommand(Query, MysqlConn)
READER = Command.ExecuteReader
While READER.Read
TextBox1.Text = READER.GetString("name")
End While
End Try
Here is my answer. Please don't get overwhelmed by it. ;)
Broken code
First of all, as I see it, the code you provided cannot work at all, because:
your Query variable is initialized in an invalid (or at least a very exotic) way. You probably want to use something like:
Dim Query As String
Query = "select * from database.usernames where name='" & ComboBox1.Text & "'"
or in a single line:
Dim Query As String = "select * from database.usernames where name='" & ComboBox1.Text & "'"
you try to assign the connection string to the ConnectionString property of a nonexistent Mysql variable. Or the variable exists because it is declared somewhere else, which might be a bug in your code snippet here. But I assume you want to assign the connection string to the MysqlConn.ConnectionString property instead.
you have not declared the MysqlConn and Command variables anywhere. You only just assign to them. (I will simply assume you have declared the variables correctly somewhere else in your code...)
the IDataRecord interface does not provide a GetString(name As String) method overload. So unless you have defined a custom extension method for it, you probably need to use the IDataRecord.GetOrdinal(name As String) method as well, or use the column index instead of the column name.
Anyway, the code you provided uses MySQL. So I assume that MySQL is the "SQL Database" you are using successfully. And that seems to work, as you say? Well... Hmmm... Then I will simply assume your code snippet is completely correct and works perfectly with MySQL... :/
MS Access vs. MySQL
Using MS Access requires other data access classes (probably the ones in namespace System.Data.OleDb) and another connection string. You could take a look at this ADO.NET OleDb example for MS Access in the Microsoft documentation.
You probably even have to update your SQL query, because every database system uses its own SQL dialect. You might want to consult the Office documentation for that. But your query is quite simple, so perhaps all you have to do to make it work with MS Access is:
remove the database name and use only the table name, and
delimit the name identifier (since it is a reserved keyword in MS Access).
I personally delimit all identifiers in my SQL queries, just to avoid unintended conflicts with reserved keywords. So I would personally use something like this:
select * from [usernames] where [name] = '...'
Additional tips
Also, I would like to provide you some additional (unrelated) tips regarding improving your code:
Use Using-statements with variables of an IDisposable type as much as possible. Those types/classes do not implement that interface if there isn't a good reason for it, so I consider it not unimportant to call Dispose when you are done with such disposable objects (or using a Using statement to call Dispose implicitly).
Use SQL parameters (if possible) to avoid SQL injection vulnerabilities. Look at this StackOverflow question and its answer for an example of how to use SQL parameters with MS Access.
Example
You may take a look at the following code snippet. It might not provide a working example out-of-the-box, but you might get some useful/practical ideas from it:
Dim connectionString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Data\\database.mdb;User Id=admin;Password="
Dim query As String = "select * from [usernames] where [name] = #Name"
Using conn As New OleDbConnection(connectionString)
Using command As New OleDbCommand(query)
command.Parameters.Add("#Name", OleDbType.VarChar, 50).Value = ComboBox1.Text
conn.Open()
Using reader As OleDbDataReader = command.ExecuteReader
If reader.Read Then
textbox1.Text = reader.GetString(reader.GetOrdinal("name"))
End If
End Using
End Using
End Using
I am writing code to insert a username and password into a database called Users.
When I try to run the code it says there is an error in the INSERT statement's syntax but I cannot for the life of me find it.
I am running the SQL statement using another function called RunSQL that I can submit if need be but its worked fine with every other SQL statement I have run with it.
The Users table has the following columns with their data type
User_ID - Auto Number (Primary Key)
Username - Short Text
Password - Short Text
I have tried adding ' ' around the values I am going to insert into the table as well as removing the & and making it one continuous string. I have tried adding / removing the ; but nothing has worked.
Dim sql As String = "INSERT INTO Users (Username, Password) " &
"VALUES (" & username_Textbox.Text & " , " & password_Textbox.Text & ");"
RunSQL(sql)
MessageBox.Show("User Added")
Private Sub RunSQL(ByVal sql As String)
Dim conn As OleDbConnection = New
OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Paper_Gen_Database.accdb;")
conn.Open()
Dim cmd As New OleDbCommand(sql, conn)
cmd.ExecuteNonQuery()
System.Threading.Thread.Sleep(500)
End Sub
The code should take the values from the username and password textboxes and insert them into the Users table but so far it has only thrown back an SQL error.
This is what the SQL statement looks when with "bh106" being the Username and "ZLTga" being the Password
This is one way to use parameters. It is very important to use parameters because otherwise you risk SQL injection which can ruin your database. It is actually much easier to write the SQL statement this way because you don't have to worry about if you have all your quotes in the string correctly.
The Using...End Using blocks ensure that your database objects are closed and disposed even if there is an error. This is important because it releases any unmanaged resources being used.
In a real application you would never save passwords as plain text but that is a subject for another day.
Private Sub InsertUser()
Dim sql As String = "INSERT INTO Users (Username, [Password]) VALUES (#username, #password);"
Using conn As OleDbConnection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Paper_Gen_Database.accdb;")
Using cmd As New OleDbCommand(sql, conn)
cmd.Parameters.Add("#username", OleDbType.VarChar).Value = username_Textbox.Text
cmd.Parameters.Add("#password", OleDbType.VarChar).Value = password_Textbox.Text
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
MessageBox.Show("User Added")
End Sub
In Access the order that the parameters are added must match the order that they appear in the SQL statement.
Try this (its probably because of lack of quotes, and also because password is protected word):
Dim sql As String = "INSERT INTO Users (Username, [Password]) " &
"VALUES ('" & username_Textbox.Text & "' , '" & password_Textbox.Text & "');"
RunSQL(sql)
MessageBox.Show("User Added")
Also be aware of sql injection problem.
If a user will put a quote inside a textbox, insert will still fail.
You should try converting your code into parametrized query, example:
https://learn.microsoft.com/pl-pl/dotnet/api/system.data.oledb.oledbcommand.parameters?view=netframework-4.7.2
I am new to this forum, please could you help me get this code to work, when i execute it, it simply does nothing and does not update the DB. If i remove the square brackets it gives an error: "SYNTAX ERROR in UPDATE statement"
Any help appreciated!
Dim connection As OleDbConnection
connection = New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=UserDB.accdb;Jet OLEDB:Database;")
connection.Open()
Dim pass As String
pass = txtconfirm.Text
Dim user As String
user = LoginForm.UsernameTextBox.Text
Dim query As String = "UPDATE [Users] SET [Password]= '" & pass & "' WHERE [Username]= '" & user & "';"
Dim command As New OleDbCommand(query, connection)
command.ExecuteNonQuery()
connection.Close()
Given your actual connection string, the database that will be updated is the one in the directory where your application starts. This means that if you work with a WinForms application this folder is \BIN\DEBUG or x86 variant. If there is not error then you could get the return value of the ExecuteNonQuery call to verify if a record has been updated or not
Dim rowsUpdated = command.ExecuteNonQuery()
MessageBox.Show("Record updated count = " & rowsUpdated)
If this value is not zero then your database has been updated and you are looking for changes in the wrong database. Check the one in the BIN\DEBUG folder.
In any case your code has big problems. If your variables user or pass contain a single quote, then your code will crash again because your string concatenation will form an invalid SQL. As usual the only workaround is to use a parameterized query
Dim pass = txtconfirm.Text
Dim user = LoginForm.UsernameTextBox.Text
Dim query As String = "UPDATE [Users] SET [Password]= #p1 WHERE [Username]= #p2"
Using connection = New OleDbConnection("...........")
Using command As New OleDbCommand(query, connection)
connection.Open()
command.Parameters.Add("#p1", OleDbType.VarWChar).Value = pass
command.Parameters.Add("#p2", OleDbType.VarWChar).Value = user
command.ExecuteNonQuery()
End Using
End Using
The parameterized approach has many advantages. Your query text is more readable, there is no misunderstanding between your code and the values expected by your database engine. And while not easy to exploit with MS-Access there is no problem with Sql Injection
I think Steve presents a much better approach for you coding this...
Let me just throw out a few more things:
The reason you can't take those brackets out is some of your column names are reserved words; just FYI.
Since you report "it does nothing..." when you execute, it sounds like you have a valid connection and sql syntax, in which case my next step would be to copy the sql command text while in debug mode, change it to a select and run it in your DB. You should get one result when you do. If not, either your criteria or field contents are not what you think they are...
Just change the Update table SET field-value ... to SELECT * FROM table and leave the WHERE clause as is.
i have problem trying to delete record from my VS 2012 and i'm using sql server 2012, this is my task from my lecturer, and i cant solved it
now this is what i have
Private Sub bt_hapus_Click(sender As Object, e As EventArgs) Handles bt_hapus.Click
Try
Dim sqlda As New SqlClient.SqlDataAdapter("Delete from tabelpasien where No_Rkm_Mds=" & Me.txt_rkm_mds.Text, Me.SqlConnection1)
sqlda.Fill(dspasien, "tabelpasien")
MsgBox("Data telah berhasil dihapus")
bersih()
pasif()
normal()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
any help would be greatly apreciated...
A delete command is executed using an SqlCommand and the ExecuteNonQuery method.
Your code should be
Try
Dim cmd = New SqlClient.SqlCommand("Delete from tabelpasien where No_Rkm_Mds=#rkm", Me.SqlConnection1)
cmd.Parameters.AddWithValue("#rkm", Me.txt_rkm_mds.Text)
cmd.ExecuteNonQuery()
....
Using a parameterized query you don't have to put quotes around your where values (if the underlying field is any kind of char/varchar/nvarchar type) but, the most important benefit of a parameterized query is the elimination of a possible Sql Injection attack
You have forgotten your single quote marks I.E." ' " from around your condition.
Your statement Should be
Delete From tabelpasien where No_Rkm_Mds='" + Me.txt_rkm_mds.Text + "'"
If this is SQL SERVER, there shouldn't be a FROM in the statement.
Dim sqlda As New SqlClient.SqlDataAdapter("DELETE tabelpasien where No_Rkm_Mds=" & Me.txt_rkm_mds.Text, Me.SqlConnection1)
If No_Rkm_Mds is a VARCHAR or NVARCHAR, etc..., the value must be wrapped in 's.
Dim sqlda As New SqlClient.SqlDataAdapter("DELETE tabelpasien where No_Rkm_Mds=`" & Me.txt_rkm_mds.Text & "`", Me.SqlConnection1)
Finally, you should consider using SQL Parameters to avoid SQL injection.
I'm developing a VB.NET application to obtain data from any data source (using an odbc connection string), and because this I can't use specific .net connectors like MySql.Net connector and I can't previously know if the file/DMBS supports LIMIT parameter. This app will read data from a table in the data source and use the information to make some files. At this point there was no problem with some tables because they are less than 3,000,000 records length, but there is a table that has 5,000,000+ rows length, and when I send the query the connection is lost. I'm working with OdbcDataReader, because I read on MSDN site that this is the best way to read a table one row at time and I just use each record once.
This is an example of my code:
Private Sub ReadData()
dim cnn as odbc.odbcConnection
dim coma as odbc.odbcCommand
dim reg as odbc.odbcDataReader
try
cnn=new odbc.odbcConnection("Driver={MySQL ODBC 3.51 Driver}; server=localhost; Database=datos; User=usuario; Password=contrasenia; option=3;")
cnn.open()
coma=new odbc.odbcCommand("select * from tabla")
reg=coma.ExecuteReader()'<- when this line is executed fails with the 5,000,000+ length table.
catch ex as Exception
MessageBox("Error: "+ex.Message,MsgBoxStyle.Critical,"Error")
end try
... 'Do anything with the data
end sub
In VBA or VB6 I do something like this:
Private Sub ReadData()
dim cnn as object
dim tab as object
set cnn = CreateObject("ADODB.Connection")
set tab = CreateObject("ADODB.Recordset")
cnn.cursorlocation=3
cnn.open "Driver={MySQL ODBC 3.51 Driver}; server=localhost; Database=datos; User=usuario; Password=contrasenia; option=3;"
tab.open "tabla", cnn,,2
...'Do anything with the data
end sub
And this code is executed without problem.
Any idea how to retreive data in a more efficent way in VB.NET? Or there is any way to do like ADODB (just indicating the table name not the SQL sentence).
Sorry if anything is incomprehensible.
Perhaps try setting the ConnectionTimeout property? Try adding this line before your cnn.open() call:
cnn.ConnectionTimeout = 50000 ' Number of seconds before timeout
When I had similar problem, my solution was to add LimitQuery function that added keywords to query to limit the number of results depending on the provider.
Something like this:
Public Function LimitQuery(ByVal query As String, ByVal RowLimit As Integer) As String
If RowLimit > 0 Then
Select Case m_DbType
Case DbType.Oracle
return "SELECT * FROM(" & query & ") WHERE ROWNUM<" & cstr(RowLimit + 1)
Case DbType.SQLServer
return Replace(query, "SELECT", "SELECT TOP " & cstr(RowLimit), 1, 1)
Case DbType.MySQL
return query & " LIMIT " & cstr(RowLimit)
End Select
Else
return query
End If
End Function
This is jast a quick hack, if you want to use any data source, sooner or later, you'll need some database abstraction layer.