MySQL Query with MySQLParameters in C# - c#

I am currently developing an Application for Windows using MySQL and C#. I have the following code:
private void cboCategories_SelectedIndexChanged(object sender, EventArgs e)
{
DatabaseWork dbase = new DatabaseWork();
try
{
dbase.openConnection();
string query = "SELECT * FROM budgetcategory WHERE budc_userID=#userID AND budc_category=#category";
MySqlCommand cmd = new MySqlCommand("", dbase.conn);
cmd.CommandText = query;
cmd.Parameters.AddWithValue("#userID", userID);
cmd.Parameters.AddWithValue("#category", cboCategories.SelectedItem.ToString());
MySqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
setCatId(reader.GetString("budc_category_id"));
Console.WriteLine("Category ID: " + getCatId());
}
}
catch (MySqlException ex)
{
Console.WriteLine("Cat Error: " + ex.Message);
}
finally
{
dbase.closeConnection();
}
}
For some reason when I debug the code it never goes into the while loop as if nothing was ever returned from the database. But I know there should be something in there.
Thanks for any help you can provide

Just trying to help you debug a little:
Try reducing these three lines:
string query = "SELECT * FROM budgetcategory WHERE budc_userID=#userID AND budc_category=#category";
MySqlCommand cmd = new MySqlCommand("", dbase.conn);
cmd.CommandText = query;
to just:
string query = "SELECT * FROM budgetcategory WHERE budc_userID=#userID AND budc_category=#category";
MySqlCommand cmd = new MySqlCommand(query, dbase.conn);
Now put a breakpoint on those lines that add the parameters, and make sure that userID and especially cboCategories.SelectedItem.ToString() have the values that you expect.
Also, can you confirm that no exception is thrown?
If this is not the case run the query, with those exact values directly against the database and confirm that something is returned.

Related

C#, Refresh combo box after adding data

I have read many other questions about this same thing but it seems the answers do not pertain to how I am performing my code. After adding or deleting a record or row of information to my database from the user interface it does not show in the combo boxes until I restart the application. Maybe someone can enlighten me as I am somewhat new to this. Below is my code when clicking the add button.
private void FBinterface_Load(object sender, EventArgs e)
{
txtSerial.Focus();
try
{
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
string SerialQuery = "select SerialNumber from Inventory";
command.CommandText = SerialQuery;
//TO READ DATA
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
comboSerial.Items.Add(reader["SerialNumber"]);
}
connection.Close();
}
catch (OleDbException ex)
{
MessageBox.Show(ex.Message);
connection.Close();
}
private void btnAdd_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(txtSerial.Text))
{
try
{
connection.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
command.CommandText = #"insert into
Inventory(SerialNumber,PartNumber,ROnumber,Location)
values ('" +
txtSerial.Text + "','" +
txtPart.Text + "','" +
txtRO.Text + "','" +
txtLocation.Text + "')";
//TO READ DATA
command.ExecuteNonQuery();
MessageBox.Show("Inventory Added");
txtPart.Clear();
txtSerial.Clear();
txtRO.Clear();
txtLocation.Clear();
if (dataGridFB.DataSource != null)
{
dataGridFB.DataSource = null;
}
else
{
dataGridFB.Rows.Clear();
}
txtSerial.Focus();
connection.Close(); // CLOSE HERE OR
// YOU CANNOT ENTER RECORDS SIMULTANEOUSLY
}
catch (OleDbException ex)
{
MessageBox.Show(ex.Message);
connection.Close();
}
}
}
As a simple fix, you may add the following code snippet before the line connection.Close() in the btnAdd_Click event handler:
OleDbCommand command = new OleDbCommand();
command.Connection = connection;
string SerialQuery = "select SerialNumber from Inventory";
command.CommandText = SerialQuery;
//TO READ DATA
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
comboSerial.Items.Add(reader["SerialNumber"]);
}
This code snippet will essentially re-bind the ComboBox comboSerial. The same goes to other ComboBoxes if their underlying data is affected by btnAdd_Click procedure. Furthermore, it could be fruitful to create a dedicated procedure (something like ResfreshAllComboBoxes()), place the code similar to the sample snippet above and call it after underlying data change.
Hope this may help.
It's better to put codes in (FBinterface_Load) inside a new method, say FillComboSerial(), and then you have to call that method after inserting each new record right after closing the connection.

How can I get combobox ID to return to database

void fill_cbcategoria()
{
try
{
con.Open();
string Query = "select * from Categoria";
SqlCommand createCommand = new SqlCommand(Query, con);
SqlDataReader dr = createCommand.ExecuteReader();
while (dr.Read())
{
string categoria = (string)dr.GetString(1);
cbcategoria.Items.Add(categoria);
}
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I am using this code to fill my category combobox:
private void btneditar_Click(object sender, EventArgs e)
{
try
{
con.Open();
string Query = "insert into dbPAP.Categoria (id_categoria, categoria)" + "values('" + this.cbcategoria.SelectedValue + this.cbcategoria.SelectedItem + "') ;";
SqlCommand createCommand = new SqlCommand(Query, con);
SqlDataReader dr = createCommand.ExecuteReader();
MessageBox.Show("Editado com sucesso!");
while (dr.Read())
{
}
con.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Now I want to update data to database, but is needed "id_categoria" but I don''t know how can I do it. In Table "Categoria" just got 2 parameters, that's "id_categoria" = 0 and "categoria" = 1. Problem is, can I get "id_categoria" value to update in database using combobox.SelectedItem?
Use executeNonQuery for executing insert command. SqlDataReader is usually used for read data from the database; you can try like the following:
string Query = "insert into dbPAP.Categoria (id_categoria,categoria)values(#selectedVal,#selectedItem)";
SqlCommand createCommand = new SqlCommand(Query, con);
createCommand.Parameters.Add("#selectedVal", SqlDbType.VarChar).Value = this.cbcategoria.SelectedValue;
createCommand.Parameters.Add("#selectedItem", SqlDbType.VarChar).Value = this.cbcategoria.SelectedItem;
createCommand.ExecuteNonQuery();// return 1 in this case if insert success
few suggestions for better understanding:
ExecuteReader : ExecuteReader used for getting the query results as a DataReader object. It is readonly forward only retrieval of records and it uses select command to read through the table from the first to the last.
ExecuteNonQuery : ExecuteNonQuery used for executing queries that does not return any data. It is used to execute the sql statements like update, insert, delete etc. ExecuteNonQuery executes the command and returns the number of rows affected.
You can read more about The purpose of parameterized queries

C# checking if order number already exists

I've been looking into How to check user id already exists to see how to do this.
I am trying to get this working in my code, however it's not working. I don't get errors or something, but it just write data in database even if order number already exists.
The function:
private void createorderButton_Click(object sender, EventArgs e)
{
SqlConnection myConnection = dbHelper.initiallizeDB();
String query = "INSERT INTO testtabel (knaam, korder) VALUES ('" + knaamTextBox.Text + "','" + kordernrTextBox.Text + "')";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
SqlParameter param = new SqlParameter();
param.ParameterName = "#korder";
param.Value = kordernrTextBox.Text;
cmd.Parameters.Add(param);
//sqlCommand.Connection.Open();
SqlDataReader reader = sqlCommand.ExecuteReader();
if (reader.HasRows)
{
MessageBox.Show("Order already exist");
}
else
{
reader.Close();
}
// opens execute non query
int rows_inserted = sqlCommand.ExecuteNonQuery();
if (rows_inserted > 0)
{
label2.Text = "Order has been created";
}
else
{
Console.Write("Oops! Something wrong!");
}
}
Sorry for this kinda well known and duplicated question, but for some reason I can't get it working.
You called the wrong command, change
SqlDataReader reader = sqlCommand.ExecuteReader();
to
SqlDataReader reader = cmd.ExecuteReader();
The problem is here:
SqlDataReader reader = sqlCommand.ExecuteReader();
You should execute the other command first
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
The latter command, when will be executed will tell you if there is any record in the testtabel table. If there is, then you should show the message:
Order already exist
Otherwise, you will execute your first command, that will insert the rows.
By the way, please try to avoid string concatenation, when you write sql queries. It is one of the most well known security holes. You code is open to SQL injections. You could use parameterized queries:
String query = "INSERT INTO testtabel (knaam, korder) VALUES (#knaam, #korder)";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
sqlCommand.Parameters.Add(new SqlParamete("#knaam",knaamTextBox.Text));
sqlCommand.Parameters.Add(new SqlParamete("#korder",kordernrTextBox.Text));
While your code is full of problems (magic pushbutton, SQL injections, absence of usings), there is main one. The approach you want to implement will fail on concurrent inserts, and must not be used.
Imagine, that two users run this code against the same database, using the same korder value:
1st executes SELECT - record with the given value doesn't exist;
2nd executes SELECT - record with the given value doesn't exist;
1st executes INSERT - record with the given value does exist;
2nd executes INSERT - ooops... we have a duplicate;
To avoid duplicates you must use unique indexes in database. Do not rely on your code.
You check HasRows for INSERT INTO testtabel bla...bla..bla.. not for `elect * from testtabel where korder'
Maybe you can use this (it comes from my head and not compiled, please adjust it with your own case)
private void createorderButton_Click(object sender, EventArgs e)
{
SqlConnection myConnection = dbHelper.initiallizeDB();
String query = "INSERT INTO testtabel (knaam, korder) VALUES ('" + knaamTextBox.Text + "','" + kordernrTextBox.Text + "')";
SqlCommand sqlCommand = new SqlCommand(query, myConnection);
SqlCommand cmd = new SqlCommand("select * from testtabel where korder = #korder", myConnection);
SqlParameter param = new SqlParameter();
param.ParameterName = "#korder";
param.Value = kordernrTextBox.Text;
//sqlCommand.Connection.Open();
SqlDataReader cmdReader = sqlCommand.ExecuteReader();
if (cmdReader.HasRows)
{
MessageBox.Show("Order already exist");
}
else
{
cmdReader.Close();
}
SqlDataReader reader = sqlCommand.ExecuteReader();
// opens execute non query
int rows_inserted = sqlCommand.ExecuteNonQuery();
if (rows_inserted > 0)
{
label2.Text = "Order has been created";
}
else
{
Console.Write("Oops! Something wrong!");
}
}

Can't retrieve data from SqlDataReader in C#

I need to insert values into several tables first I have to retrieve university id from table college and then insert faculty name into table faculty and get generated by SQL Server ID. After all of this I have to insert both ids into an other table.
Problem is that I have to close readers and after I do it I can't retrieve those ids from them so variable where they should be saved is null. Here is my code. How to do it correctly?
Sorry I am new to C# and SQL Server.
// reading data into combobox
try
{
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select * from colege", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
comboBox1.Items.Add(myReader["name"].ToString());
// Console.WriteLine(myReader["Column2"].ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
myConnection.Close();
private void button1_Click(object sender, EventArgs e)
{
string item = comboBox1.Text.ToString();
// MessageBox.Show(item);
SqlConnection myConnection = new SqlConnection("user id=bogdan_db;" +
"password=1234;server=localhost;" +
"Trusted_Connection=yes;" +
"database=cafedrascience; " +
"connection timeout=30");
try
{
myConnection.Open();
}
catch (Exception E)
{
Console.WriteLine(E.ToString());
}
// reading data into combobox
String colegeid = null;
try
{
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
colegeid = myReader["id"].ToString();
// Console.WriteLine(myReader["Column2"].ToString());
}
myReader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
String facultyid = null;
try
{
SqlDataReader myReader1 = null;
SqlCommand myCommand = new SqlCommand("select * from depart where name like'" + textBox1.Text + "'",
myConnection);
myReader1 = myCommand.ExecuteReader();
while (myReader1.Read())
{
facultyid = myReader1["id"].ToString();
}
myReader1.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
SqlCommand myCommand1 = new SqlCommand("INSERT INTO coledge_faculty (coledge_id, faculty_id) " +
"Values ('"+colegeid+"''"+facultyid+"')", myConnection);
myCommand1.ExecuteNonQuery();
// MessageBox.Show(colegeid);
// MessageBox.Show(facultyid);
myConnection.Close();
}
The number one thing I can stress about your code is that you should be using parameterised queries, beyond the obvious risks of SQL Injection, it also protects you against malformed SQL, data truncation through conversion, and it allows you to use cached execution plans.
The next thing to point out is that you should not be using SELECT * in production code, e.g.
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
colegeid = myReader["id"].ToString();
// Console.WriteLine(myReader["Column2"].ToString());
}
Why bother retrieving all the columns of colege from the database, then sending them all over the network if you only care about the column id?
Finally your diagnosis of the problem is not correct:
Problem is that I have to close readers and after I do it, I can't retrieve those ids from them, so variable where they should be saved is null
If you assign the string variable colegeid a value you have retrieved from a data reader, it will not be null after you have closed the reader, it will retain the value you assigned. The most likely reason the variable is null is because your reader returns no rows so you never assign it a value.
Now, rant over, I will actually answer your question. You are massively over complicating the issue, you do not need to retrieve the values into your application tier only to insert them to another table, you can do this all in a single query in your database:
INSERT INTO coledge_faculty (coledge_id, faculty_id)
SELECT c.id, d.id
FROM depart AS d
CROSS JOIN colege AS c
WHERE d.Name = #Depart
AND c.Name = #Colege;
Then it would just be a case of calling this SQL from C#:
string item = comboBox1.Text.ToString();
string connectionString = "user id=bogdan_db; password=1234;server=localhost; Trusted_Connection=yes; database=cafedrascience; connection timeout=30";
string sql = #"INSERT INTO coledge_faculty (coledge_id, faculty_id)
SELECT c.id, d.id
FROM depart AS d
CROSS JOIN colege AS c
WHERE d.Name = #Depart
AND c.Name = #Colege;";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#Colege", SqlDbType.VarChar, 50).Value = item;
command.Parameters.Add("#Depart", SqlDbType.VarChar, 50).Value = textBox1.Text;
connection.Open();
command.ExecuteNonQuery();
}
It is usually a good idea to use using blocks with objects that implement IDisposable, this will ensure the resources are freed up when you are done with them (Don't confuse this with not being able to reuse the connection, .NET has connection pooling in the background so it will reuse connections for you, you shouldn't keep your SqlConnection object open available in case you need to use it again).
On another unrelated note, I also think you are too liberal with try/catch blocks, or at least not dealing with the exception properly, using this one as an example:
try
{
myConnection.Open();
}
catch (Exception E)
{
Console.WriteLine(E.ToString());
}
If myConnection.Open() does throw an error, you still carry on with the method. You will carry on until you get to here:
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
Where you will get another exception, something along the lines of the command requiring an open and available SqlConnection, so you go to the exception.
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Again you don't exit the method, but carry on, and you will get the same error later when you try and use the connection again. Again the method carries on and you will use the closed connection a third time to try and insert two variables that were never assigned because exceptions were thrown into your database. Fine, use try catch blocks, but do something meaningful with the exception and exit the method.
private void BtnAdd_Click(object sender, EventArgs e)
{
//con.Open();
cmd = new SqlCommand("INSERT INTO TBL_STORE VALUES (N'"+txt_store_name.Text.Trim()+"',N'"+txt_store_adress.Text.Trim()+"',N'"+txt_store_mobile_1.Text.Trim()+"',N'"+txt_store_mobile_2.Text.Trim()+"',N'"+txt_store_Manger.Text.Trim()+"',N'"+txt_store_Details.Text.Trim()+"')");
cmd.Connection = con;
cmd.ExecuteNonQuery();
cmd.Parameters.AddWithValue("#store_name", txt_store_name.Text.Trim());
cmd.Parameters.AddWithValue("#store_adress", txt_store_adress.Text.Trim());
cmd.Parameters.AddWithValue("#store_mobile_1", txt_store_mobile_1.Text.Trim());
cmd.Parameters.AddWithValue("#store_mobile_2", txt_store_mobile_2.Text.Trim());
cmd.Parameters.AddWithValue("#store_manger", txt_store_Manger.Text.Trim());
cmd.Parameters.AddWithValue("#store_details", txt_store_Details.Text.Trim());
cmd.Parameters.AddWithValue("#Id_store", txt_store_number.Text.Trim());
con.Close();
lbl_store.Text="insert is sucess";
//cmd.Parameters.Add("#store_name", SqlDbType.NVarChar, 50).Value = txt_store_name.Text.Trim();
}

SQL delete command?

I am having trouble with a simple DELETE statement in SQL with unexpected results , it seems to add the word to the list??. Must be something silly!. but i cannot see it , tried it a few different ways. All the same result so quite confused.
public void IncludeWord(string word)
{
// Add selected word to exclude list
SqlConnection conn = new SqlConnection();
String ConnectionString = "Data Source = dev\\SQLEXPRESS ;" + "Initial Catalog=sml;" + "User id=** ;" + "Password =*;" + "Trusted_Connection=No";
using (SqlConnection sc = new SqlConnection(ConnectionString))
{
try
{
sc.Open();
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'" +
conn);
Command.Parameters.AddWithValue("#word", word);
Command.ExecuteNonQuery();
}
catch (Exception e)
{
Box.Text = "SQL error" + e;
}
finally
{
sc.Close();
}
ExcludeTxtbox.Text = "";
Box.Text = " Word : " + word + " has been removed from the Exclude List";
ExcludeLstBox.AppendDataBoundItems = false;
ExcludeLstBox.DataBind();
}
Try removing the single quotes. Also why are you concatenating your SQL string with a connection object (.. word='#word'" + conn)???
Try like this:
try
{
using (var sc = new SqlConnection(ConnectionString))
using (var cmd = sc.CreateCommand())
{
sc.Open();
cmd.CommandText = "DELETE FROM excludes WHERE word = #word";
cmd.Parameters.AddWithValue("#word", word);
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
Box.Text = "SQL error" + e;
}
...
Notice also that because the connection is wrapped in a using block you don't need to Close it in a finally statement. The Dispose method will automatically call the .Close method which will return the connection to the ADO.NET connection pool so that it can be reused.
Another remark is that this IncludeWord method does far to many things. It sends SQL queries to delete records, it updates some textboxes on the GUI and it binds some lists => methods like this should be split in separate so that each method has its own specific responsibility. Otherwise this code is simply a nightmare in terms of maintenance. I would very strongly recommend you to write methods that do only a single specific task, otherwise the code quickly becomes a complete mess.
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'" +
conn);
should be replaced with
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'",
conn);
Also try by removing single quotes as suggested by others like this
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word=#word",
conn);
The #Word should not be in quotes in the sql query.
Not sure why you're trying to add the connection on the end of the sql query either.
To debug this, examine the CommandText on the SqlCommand object. Before reading further, you should try this.
The issue comes with adding the single quotes around a string that is parameterized. Remove the single quotes and life is beautiful. :-)
Oh, and your conn is an object and needs a comma, not a +.
See the code below:
private void button4_Click(object sender, EventArgs e)
{
String st = "DELETE FROM supplier WHERE supplier_id =" + textBox1.Text;
SqlCommand sqlcom = new SqlCommand(st, myConnection);
try
{
sqlcom.ExecuteNonQuery();
MessageBox.Show("delete successful");
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
}
private void button6_Click(object sender, EventArgs e)
{
String st = "SELECT * FROM supplier";
SqlCommand sqlcom = new SqlCommand(st, myConnection);
try
{
sqlcom.ExecuteNonQuery();
SqlDataReader reader = sqlcom.ExecuteReader();
DataTable datatable = new DataTable();
datatable.Load(reader);
dataGridView1.DataSource = datatable;
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
}
See the code below:
String queryForUpdateCustomer = "UPDATE customer SET cbalance=#txtcustomerblnc WHERE cname='" + searchLookUpEdit1.Text + "'";
try
{
using (SqlCommand command = new SqlCommand(queryForUpdateCustomer, con))
{
command.Parameters.AddWithValue("#txtcustomerblnc", txtcustomerblnc.Text);
con.Open();
int result = command.ExecuteNonQuery();
// Check Error
if (result < 0)
MessageBox.Show("Error");
MessageBox.Show("Record Update of Customer...!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
con.Close();
loader();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
con.Close();
}
You can also try the following if you don't have access to some of the functionality prescribed above (due, I believe, to older versions of software):
using (var connection = _sqlDbContext.CreatSqlConnection())
{
using (var sqlCommand = _sqlDbContext.CreateSqlCommand())
{
sqlCommand.Connection = connection;
sqlCommand.CommandText = $"DELETE FROM excludes WHERE word = #word";
sqlCommand.Parameters.Add(
_sqlDbContext.CreateParameterWithValue(sqlCommand, "#word", word));
connection.Open();
sqlCommand.ExecuteNonQuery();
}
}
...
I'm an associate dev. Hence the "I believe" above.

Categories

Resources