I'm trying to remove a row from the database that has the same ART as is selected in the combobox. I had it working before but when I changed the database it was supposed to delete it from it stopped working and gave me a error message. I did change the database connection etc acording to the database change.
The error message (Hoping image works)
I don't know why it says "conversion failed when converting the varchar value 'R06018' to data type int" since I don't have a value of R06018 anywhere in the code, nor is it the selected row.
the code I tried after the delete stopped working, it's just the delete without any thing extra (I know it doesn't dispose but the program crashes when it tries to read, and it's just for finding the issue)
try
{
SqlCommand inkoopartdelete = new SqlCommand("delete from ART where ART=" + artnr.SelectedItem + "", Connectie.connMEVO);
drMEVO = inkoopartdelete.ExecuteReader();
MessageBox.Show(this.artnr.SelectedItem + " verwijderd.");
}
catch (Exception e) { MessageBox.Show("" + e); }
The old code after I changed the db connection (set as comment since I tried a smaller bit of code for the delete)
//SqlCommand inkoopdelete = new SqlCommand("delete from ART where ART=#art", Connectie.connMEVO_ART);
//inkoopdelete.Parameters.Add("#art", SqlDbType.VarChar).Value = artnr.SelectedItem;
//drMEVO = inkoopdelete.ExecuteReader();
//try
//{
// while (drMEVO.Read())
// { }
// MessageBox.Show(this.artnr.SelectedItem + " verwijderd.");
//}
//catch (SqlException v)
//{
// MessageBox.Show("" + v);
//}
//inkoopdelete.Dispose();
I hope any of you could help me, since I can't find the issue.
Found the issue, see accepted awnser for error in test code, real error seems to be me reading over a part of the code -_- ...srry
If the ART field is of type nvarchar then, if you really want to use string concatenations, you should enclose your string value in single quotes and write
SqlCommand inkoopartdelete = new SqlCommand(#"delete from ART
where ART='" + artnr.SelectedItem + "'", Connectie.connMEVO);
That's a valid enough reason to revert as soon as possible to use a parameterized query as you have initially. Other reasons to avoid this is the fact that if your value has an embedded single quote the Whole text becomes syntactically wrong. And, finally, string concatenation is the open door for Sql Injection Attacks
A last note. If you want to execute a query like DELETE/INSERT or UPDATE do not use ExecuteReader. It works, but it is not necessary to build an SqlDataReader for that kind of queries. Just use
int affectedRows = inkoopartdelete.ExecuteNonQuery();
Change below statement :
You have to give single quote.
SqlCommand inkoopartdelete = new SqlCommand("delete from ART where ART='" + artnr.SelectedItem + "'", Connectie.connMEVO);
Related
I'm trying to update a Database table and getting the error
"MySql.Data.MySqlClient.MySqlException: 'You have an error in your SQL
syntax; check the manual that corresponds to your MySQL server version
for the right syntax to use near 'group='superadmin' WHERE
identifier='steam:steam:1100001098b5888'' at line 1'"
// Creates query to run
public void UpdateInfo(String jobTitle, int jobGrade, String adminLevel, String identifier) {
// Opens the database connection if it's not already open
if (!(databaseConnected)) {
openConnection();
}
// Creates query to run
String query = "UPDATE " + table + " SET job=#jobTitle, job_grade=#jobGrade, group=#adminLevel WHERE identifier=#identifier";
// Makes a new command
MySqlCommand cmd = new MySqlCommand(query, connection);
// Replaces the # placeholders with actual variables
cmd.Parameters.AddWithValue("#jobTitle", jobTitle);
cmd.Parameters.AddWithValue("#jobGrade", jobGrade);
cmd.Parameters.AddWithValue("#adminLevel", adminLevel);
cmd.Parameters.AddWithValue("#identifier", identifier);
// Executes it and if it's...
if (cmd.ExecuteNonQuery() > 0) {
// Successful
MessageBox.Show("Successfully updated information");
closeConnection();
return;
} else {
// Not successful
MessageBox.Show("Error with updating information!");
// Closes the connection again to prevent leaks
closeConnection();
return;
}
}
I tried your query on https://sqltest.net/ and noticed it highlighted "group" when I tried to create the table. I'm wondering if the problem might be the usage of "group" as a column name since it's a reserved word.
Is it possible to try renaming the column to group_level or adding back ticks around 'group' or "group" and seeing if that works?
So for example
'group'=#grouplevel
I found this thread and this thread on renaming the column where they had issues with "group" as a column name. Adding backticks seemed to solve both problems.
EDIT: As per OP, double quotes (") solved the issue instead of single. Edited answer to include.
Try change query like this
String query = "UPDATE " + table + " SET job='#jobTitle', job_grade=#jobGrade, group='#adminLevel' WHERE identifier='#identifier'";
if you input String value with query, you need to use 'this' for work
I hope this will work for you.
if not, you can use String.Format for that like this.
String Query = String.Format("Update `{0}` Set job='{1}', job_grade={2}, group='{3}' Where identifier='{4}'", table, jobTitle, jobGrade, adminLevel, identifier);
I'm having problems with some code I'm trying to write. I'm doing something for suppliers orders, so I have a table which is named "encomendas_fornecedores" with a autoincrement field before the key that is the code of sale which consists in a EF before the number(which is a text field).
Here is the code:
connection.Open();
OleDbCommand comando1 = new OleDbCommand();
OleDbCommand comando2 = new OleDbCommand();
OleDbCommand comando3 = new OleDbCommand();
comando1.Connection = connection;
comando2.Connection = connection;
comando3.Connection = connection;
comando1.CommandText = "INSERT INTO encomendas_fornecedores (cod_encomenda_forn, cod_metodo, cod_forn, total_pagar_forn) VALUES('FO', '" + txtcodmetodo.Text + "', '" + txtcodforn.Text + "', '" + lbltotalapagar.Text + "'); ";// insert into table the values with a FO to cod
comando1.ExecuteNonQuery();
comando2.CommandText = "Select MAX(num_encomenda) From encomendas_fornecedores;";// selecting maximum num encomenda so I can isolate it and add to a text before(btw I do this in php/sql no problems
int numero = Convert.ToInt32(comando2.ExecuteScalar());//max num_encomenda
string codencomendaforn= "EF"+Convert.ToString(numero);// sales code completed
comando3.CommandText = "UPDATE encomendas_fornecedores SET cod_encomenda_forn = '"+codencomendaforn+"' WHERE num_encomenda = '"+ numero +"';";//query that is giving me the problems, it says something like "type of data incorrect in data expression"
comando3.ExecuteScalar();//giving me error this line
connection.Close();
But now here's the catch the cod_encomenda_forn is text and the num_encomenda auto increment as it is in the sql, and I tried to show the query in a textbox to see if its anything is wrong but nothing seems wrong.
"UPDATE encomendas_fornecedores SET cod_encomenda_forn = '"+codencomendaforn+"' WHERE num_encomenda = **'**"+ **numero** +"**'**;";//query that is giving me the problems,it says something like "type of data incorrect in data expression"
You are passing a string numero to a where statement that seems like it is expecting a number. As long as it is numeric it should work, but definitely not gauranteed to work. Second you are passing anothercodencomendaforn string to encomenda what is encomenda 's data type?
It appears that you are not handling potential datatype differences between your c# code and your SQL query. In addition single quoting '' around a value in a SQL statement tells the database engines that it is a string even if that is '1234'. While SQL will automatically convert some values it doesn't always. In addition c# .net library also looks for some conversion etc. before sending the SQL statement. To fix appropriately use parameters that are data typed to the database type in the SQL table. To fix it simply in the statement figure out your data types and fix the '' single quotes appropriately.
PS the people trying to help you in the comments were being nice and telling you the professional way of keeping your job in the future when you graduate after fixing this issue.
I have a DataGridView which displays a list of students and their info in a table.
One column named "Grade" is editable so I wish to reflect all changes to the database when the user clicks the "Save Changes" button.
I've wrote this code but for some reason it doesn't work:
private void bttnStudentsSaveChanges_Click(object sender, EventArgs e)
{
try
{
if (connection.State == ConnectionState.Closed) connection.Open();
DataTable changes = ((DataView)dataGridViewStudents.DataSource).Table.GetChanges();
if (changes != null)
{
foreach (DataRow row in changes.Rows)
{
MySqlCommand updateCommand = connection.CreateCommand();
updateCommand.CommandText = #"UPDATE grades
INNER JOIN lectures ON grades.idLecture = lectures.id
INNER JOIN students ON grades.idStudent = students.id
SET grades.grade = '" + row["Grade"] + #"'
WHERE students.id = '" + row["ID"] +
#"' AND (students.name = '" + row["Name"] +
#"' AND students.surname = '" + row["Surname"] +
"') AND lectures.name = '" + row["Lecture"] + "'";
updateCommand.ExecuteNonQuery();
}
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
When this executes there are no changes made to the database.
Since I have to join multiple tables I can't use MySqlCommandBuilder (at least i think that's the reason since I've tried it and got an error about it) so i decided to do it manually.
I've put a couple of breakpoints to check if the data is right and both the changes variable and the CommandText property contain valid data.
I've tested the MySQL query in SQLyog and it worked there as it should
It's as if the updateCommand.ExecuteNonQuery(); doesn't execute.
EDIT: I've added a few things but it still isn't working. The new code is
private void bttnStudentsSaveChanges_Click(object sender, EventArgs e)
{
try
{
connection.Open();
DataTable changes = ((DataView)dataGridViewStudents.DataSource).Table.GetChanges();
if (changes != null)
{
foreach (DataRow row in changes.Rows)
{
MySqlCommand updateCommand = connection.CreateCommand();
updateCommand.CommandText = #"UPDATE grades
INNER JOIN lectures ON grades.idLecture = lectures.id
INNER JOIN students ON grades.IDStudent = students.ID
SET grades.grade = #grade
WHERE students.ID = #ID AND (students.name = #name AND students.surname = #surname)
AND lectures.name = #lecture";
updateCommand.Parameters.AddWithValue("#grade", row["Grade"]);
updateCommand.Parameters.AddWithValue("#ID", row["ID"]);
updateCommand.Parameters.AddWithValue("#name", row["Name"]);
updateCommand.Parameters.AddWithValue("#surname", row["Surname"]);
updateCommand.Parameters.AddWithValue("#lecture", row["Lecture"]);
updateCommand.ExecuteNonQuery();
}
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
finally
{
if(connection.State == ConnectionState.Open) connection.Close();
}
}
EDIT2: I found out that ExecuteNonQuery returns a number of affected rows. I'm getting 0 as a result. Which is odd since the command when executed in SQLyog yields 1 row affected as a result. Weird
EDIT3: I found out what the issue is. The database contains Croatian letters (čćšđž) so when they are in a command the command doesn't execute. I think it's something to do with character encoding. When the command only contains regular(ASCII) letters then it works normally. I'm not sure how to fix it yet but at least now i know where the issue lies
EDIT4: Issue resolved. Changed the database collation to utf8
if you have integers in the database type you don't need to give single quotes for the parameters.
try without singles quotes for number types.
You can avoid all these issues and more safer way is by using parameterized query
EDIT
when you get row values you can get it based on type as below
row.Field<int>("ID")
change your code something like below, check the types again
updateCommand.Parameters.AddWithValue("#grade", row.Field<int>("Grade"));
updateCommand.Parameters.AddWithValue("#ID", row.Field<int>("ID"));
updateCommand.Parameters.AddWithValue("#name", row.Field<string>("Name"));
updateCommand.Parameters.AddWithValue("#surname", row.Field<string>("Surname"));
updateCommand.Parameters.AddWithValue("#lecture", row.Field<string>("Lecture");
This code is dangerously fragile. Picking up some connection and not being sure if it is even open is the sign of not really know what's going on. If you don't even know if you have a connection open then you probably don't know whether it's engaged in a transaction. I agree with aquaraga - it probably is but you're just so entangled you cannot tell. There could be another bug elsewhere in the code that doesn't commit.
In any case I'd suggest introducing a design pattern to centralise when you open a connection, create a transaction then do the work then commit or rollback. Doing it in UI events is a pretty bad practice to say the least. At least try to separate your UI from your business and data logic.
I am trying to update a mysql table while inside a c# for loop and a if statement well a few if statements. While running with a break point it will run the executenonquery once but the next loop it does not hit that. Even when i does hit the nonquery it does not change the table information.
the ffi string is the name of the column in my table and string val is what i want to put in. I know this is not the safe way to do it but I will change it when i can get it working the way it should.
Updated code it now runs the NONQUERY every time it should but still not updating the table
Code:
for (a = 0; a <= z; a++)
{
if (ds3.Tables[0].Rows[a][1].ToString() == dataGridView1.Rows[i].Cells[0].Value.ToString())
{
if (ds3.Tables[0].Rows[a][2].ToString() == dataGridView1.Rows[i].Cells[1].Value.ToString())
{
if (ds3.Tables[0].Rows[a][3].ToString() == dataGridView1.Rows[i].Cells[2].Value.ToString())
{
MessageBox.Show("We have a match " + dataGridView1.Rows[i].Cells[0].Value.ToString() + " " + dataGridView1.Rows[i].Cells[1].Value.ToString() + " " + dataGridView1.Rows[i].Cells[t].Value.ToString());
try
{
string ffi = textBox1.Text;
decimal val = decimal.Parse(dataGridView1.Rows[i].Cells[t].Value.ToString());
MySqlCommand cmd = new MySqlCommand("Update spt_results SET " + ffi + " = " + val + " where project_Id =" + dataGridView1.Rows[i].Cells[0].Value.ToString() + "",connection2);
//cmd.Connection = connection2;'
// cmd.Connection.Open();
cmd.ExecuteNonQuery();
//cmd.Connection.Close();
}
catch
{
}
The message box does show every loop and the connection2.open will run everytime
Thank you for looking and your help
The update string looks like "update spt_results SET FFI 300 = '15' where project_Id =AAA007" when it runs
Brent
Look at your code:
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = // ... snip SQL injection invitation
connection2.Open();
cmd.ExecuteNonQuery();
connection2.Close();
The MySqlCommand has no connection. You're opening and closing a connection, but it's got nothing to do with the command. I'd actually expect cmd.ExecuteNonQuery() to throw an exception because it has no connection...
Note that you should use using statements for the command and connection, to ensure that all the resources get cleaned up even in the face of an exception.
use cmd.Connection = connection2; just after connection2.Open();.
When you trying to execute the cmd.ExecuteNonQuery(), it is raising the error for no Connection bounded with the Command and error is caught in catch block. You didn't came to know because you have not doing anything in catch block for the errors.
If uncomment your code: The connection is open correctly and your code should work. But I'd suggest you to open connection once, before the loop, and close it at the end.
Another point is that you catched ALL exceptions, it is not good. The problem can be with the query, try to run "update spt_results SET FFI 300 = '15' where project_Id =AAA007" in the console or another MySQL client. It will throw an error. The field name 'FFI 300' must be quoted because it contains a white space and the value 'AAA007' must be quoted as a string literal. Try this query -
UPDATE spt_results SET `FFI 300` = '15' WHERE project_Id = 'AAA007'
string queryStr = "select max(patient_history_date_bio) " +
"as med_date, medication_name from biological where " +
"(patient_id = " + patientID.patient_id + ") " +
"group by medication_name;";
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand(queryStr, conn))
{
conn.Open();
using (SqlDataReader rdr = cmd.ExecuteReader())
{
int count = 0;
while (rdr.Read())
{
MessageBox.Show("test");
med.medication_date[count] = new DateTime();
med.medication_date[count] = DateTime.Parse(rdr["med_date"].
ToString());
MessageBox.Show("test2");
med.medication_name[count] = rdr["medication_name"].ToString();
count++;
}
}
conn.Close();
}
so i'm trying to read this sql statement. "test" message box displays, but not "test2". I tried running the sql statement in VS by itself (in the server explorer), and the sql statement works. it gives me what i want. but somehow, the code doesn't work... does anyone see why?
Assuming patient_id is some sort of integer (or is it a Guid), my assumption is that the current culture of your program is causing the ToString method call on int to be formatted in a way that is returning something that the parser can't parse (e.g. "1,234,567").
Generally, the way you are executing this statement is not a best-practice. While you might not be susceptible to injection attacks if the id is indeed an int (you are most definitely open to them if it's a string), you generally want to parameterize the queries.
The reason for this is not only to protect against injection attacks, but because it will properly format the parameter in the query string according to the type.
Another thing to point out about your code is how you are retrieving the values from the reader. You are effectively calling ToString on the DateTime instance, then calling Parse on the string to get a DateTime back.
This effectively burns cycles. All you need to do is cast (unbox in the case of value types) the value back.
So where you have:
med.medication_date[count] = DateTime.Parse(rdr["med_date"].
ToString());
You should have:
med.medication_date[count] = (DateTime) rdr["med_date"];
All that being said, as to why the second message box is not showing, my first guess is that you are executing this in an event handler in a Windows Forms application, and that an exception is being thrown.
I think that what you will find is that if medication_date is an array, then it hasn't been initialized and you are getting a NullReferenceException or something about the array index being out of bounds.
What is med.medication_date?
If it is an array, maybe it hasn't been initialized yet.
If it is a list, you should assign to it using med.medication_date.Add(value);
Alternatively, as everyone else is saying, the date time conversion may be at fault. Try replacing
MessageBox.Show("test");
With
MessageBox.Show(rdr["med_date"].ToString());
you should direct your debug stuff to the output window...it's muche easier to follow the flow.
system.diagnostics.debug.writeline(rdr["med_date"].ToString());
Without more info, it looks like the line
med.medication_date[count] = DateTime.Parse(rdr["med_date"].ToString());
throws an exception due to an unrecognised date, and the exception is being swallowed by a handler higher up.