button delete doesn't execute well in c# - c#

I'm stuck here again and i don't know where the problem come from !
Well, i have a delete button in c# i wrote the code and everytime i execute it they show a message.box" well deleted" but when i restarted my app i find that nothing has deleted even in my database in sql server ..please tell me what's wrong with my code:
SqlConnection sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["conn"].ConnectionString);
SqlCommand cmd = new SqlCommand();
SqlDataAdapter reader = new SqlDataAdapter();
sqlCon.Open();
string requete = "DELETE FROM [RECAP] where code_reseau='" + textBox1.Text + "' and gch_dep='" + comboBox2.SelectedText + "' and typ_port='" + comboBox3.SelectedText + "' and mois = " +Form3.mois+" and annee = "+Form3.annee+" ";
cmd = new SqlCommand(requete, sqlCon);
cmd.ExecuteNonQuery();
MessageBox.Show("Supprimé !");
sqlCon.Close();

Are you really sure that the DELETE operation succeeded? you are not checking for that and showing the success message. Rather show the message upon checking like
int recordEffected = cmd.ExecuteNonQuery();
if(recordEffected > 0)
MessageBox.Show("Supprimé !");
else
MessageBox.Show("Maximus Prime !");

Related

Invalid attempt to call read when reader is closed when inserting data

i have a button that when clicked inserts data from textbox and combobox fields into database tables, but every time i insert it gives me "Invalid attempt to call read when reader is closed". How can i get rid of this error. And tips on optimising the code are welcome, because i know im a total noob. thanks
private void btnSave_Click(object sender, RoutedEventArgs e)
{
try
{
SqlConnection sqlCon = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb; Initial Catalog=Storagedb;");
sqlCon.Open();
string Query1 = "insert into location(Storage, Shelf, columns, rows) values(" + txtWarehouse.Text + ", " + txtShelf.Text + ", " + txtColumn.Text + ", " + txtRow.Text + ")";
SqlCommand sqlCmd = new SqlCommand(Query1, sqlCon);
SqlDataAdapter dataAdp = new SqlDataAdapter(sqlCmd);
dataAdp.SelectCommand.ExecuteNonQuery();
sqlCon.Close();
}
catch (Exception er)
{
MessageBox.Show(er.Message);
}
try
{
SqlConnection sqlCon = new SqlConnection(#"Data Source=(localdb)\mssqllocaldb; Initial Catalog=Storagedb;");
sqlCon.Open();
string Query3 = "SELECT LOCATION_ID FROM LOCATION WHERE storage='" + txtWarehouse.Text + "' AND shelf='" + txtShelf.Text + "' AND columns='"
+ txtColumn.Text + "' AND rows='" + txtRow.Text + "'";
SqlCommand sqlCmd1 = new SqlCommand(Query3, sqlCon);
SqlDataReader dr = sqlCmd1.ExecuteReader(); ;
while (dr.Read())
{
string LocationId = dr[0].ToString();
dr.Close();
string Query2 = "insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID) values ('" + txtSku.Text + "','" + txtNimetus.Text + "', '"
+ txtMin.Text + "', '" + txtMax.Text + "', '" + txtQuan.Text + "', '" + LocationId + "', '" + (cbCat.SelectedIndex+1) + "', '" + (cbMail.SelectedIndex+1) + "')";
SqlCommand sqlCmd = new SqlCommand(Query2, sqlCon);
SqlDataAdapter dataAdp = new SqlDataAdapter(sqlCmd);
dataAdp.SelectCommand.ExecuteNonQuery();
}
sqlCon.Close();
}
catch (Exception ed)
{
MessageBox.Show(ed.Message);
}
}
Let's try to make some adjustments to your code.
First thing to consider is to use a parameterized query and not a
string concatenation when you build an sql command. This is mandatory
to avoid parsing errors and Sql Injections
Second, you should encapsulate the disposable objects in a using statement
to be sure they receive the proper disposal when you have finished to
use them.
Third, you can get the LOCATION_ID from your table without running a
separate query simply adding SELECT SCOPE_IDENTITY() as second batch to your first command. (This works only if you have declared the LOCATION_ID field in the first table as an IDENTITY column)
Fourth, you put everything in a transaction to avoid problems in case
some of the code fails unexpectedly
So:
SqlTransaction tr = null;
try
{
string cmdText = #"insert into location(Storage, Shelf, columns, rows)
values(#storage,#shelf,#columns,#rows);
select scope_identity()";
using(SqlConnection sqlCon = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand(cmdText, sqlCon))
{
sqlCon.Open();
using( tr = sqlCon.BeginTransaction())
{
// Prepare all the parameters required by the command
cmd.Parameters.Add("#storage", SqlDbType.Int).Value = Convert.ToInt32(txtWarehouse.Text);
cmd.Parameters.Add("#shelf", SqlDbType.Int).Value = Convert.ToInt32(txtShelf.Text);
cmd.Parameters.Add("#columns", SqlDbType.Int).Value = Convert.ToInt32(txtColumn.Text );
cmd.Parameters.Add("#rows", SqlDbType.Int).Value = Convert.ToInt32(txtRow.Text);
// Execute the command and get back the result of SCOPE_IDENTITY
int newLocation = Convert.ToInt32(cmd.ExecuteScalar());
// Set the second command text
cmdText = #"insert into product(SKU, nimetus, minimum, maximum, quantity,location_ID,category_ID,OrderMail_ID)
values (#sku, #nimetus,#min,#max,#qty,#locid,#catid,#ordid)";
// Build a new command with the second text
using(SqlCommand cmd1 = new SqlCommand(cmdText, sqlCon))
{
// Inform the new command we are inside a transaction
cmd1.Transaction = tr;
// Add all the required parameters for the second command
cmd1.Parameters.Add("#sku", SqlDbType.NVarChar).Value = txtSku.Text;
cmd1.Parameters.Add("#nimetus",SqlDbType.NVarChar).Value = txtNimetus.Text;
cmd1.Parameters.Add("#locid", SqlDbType.Int).Value = newLocation;
.... and so on for the other parameters required
cmd1.ExecuteNonQuery();
// If we reach this point the everything is allright and
// we can commit the two inserts together
tr.Commit();
}
}
}
}
catch (Exception er)
{
// In case of exceptions do not insert anything...
if(tr != null)
tr.Rollback();
MessageBox.Show(er.Message);
}
Notice that in the first command I use parameters of type SqlDbType.Int because you haven't used single quotes around your text. This should be verified against the real data type of your table columns and adjusted to match the type. This is true as well for the second command where you put everything as text albeit some of those fields seems to be integer (_location_id_ is probably an integer). Please verify against your table.

DataReader exception in C#

Let me first explain my code.
fetch fare for selected destination(reader1)
fetch * for selected user id(reader2)
insert data to process new balance(cmd3)
retrieve new balance as calculated field (reader3)
update travel account (cmd5)
clear calc_tb for next customer input(cmd6)
My problem is while running, I get this error:
There is already an open DataReader associated with this Command which must be closed first.
How can I handle more than one DataReader accessing different tables?
Is DataReader similar to resultset in Java ?
I'm a beginner in coding.
string id,
destin, num;
id = txt_id.Text;
destin = cb_destin.Text;
num = cb_num.Text;
string sql1 = "SELECT fare FROM route_info WHERE route_name='" +destin + "' ";
string sql2 = "SELECT * FROM trav_acc WHERE user_id='" + id + "'";
con.Open();
cmd1 = new SqlCommand(sql1, con);
reader1 = cmd1.ExecuteReader();
while(reader1.Read())
{
string fare = (string)reader1["fare"];
cmd2 = new SqlCommand(sql2, con);
reader2 = cmd2.ExecuteReader();
string cur_bal = (string)reader2["cur_bal"];
reader2.Close();
string calc1 = "INSERT INTO calc_tb VALUES('" + cur_bal + "','" + num + "','" + fare + "')";
string calc2 = "SELECT cur_bal - (nof_tickets * fare) AS new_bal FROM calc_tb";
cmd3 = new SqlCommand(calc1, con);
cmd3.ExecuteNonQuery();
cmd4 = new SqlCommand(calc2, con);
reader3 = cmd4.ExecuteReader();
while(reader3.Read())
{
string new_bal = (string)reader3["new_bal"];
string update = "UPDATE trav_acc SET cur_bal='" + new_bal + "',last_bal='" + cur_bal + "' WHERE user_id='" + id + "' ";
cmd5 = new SqlCommand(update, con);
cmd5.ExecuteNonQuery();
string clear = "DELETE FROM calc_tb";
cmd6 = new SqlCommand(clear, con);
cmd6.ExecuteNonQuery();
}
}
con.Close();
MessageBox.Show("Thank you for using EasyTravel.Come again soon!");
}
It seems that reader3 and cmd4 are defined outside of the code you are showing us, but at least they are defined outside the loop for reader1. So if your reader1 contains more than one row, reader3 and cmd4 will be assigned again, but the "old" reader3 is never closed. Close reader3 when it's finished reading. Or use a using statement, which will take care of the closing automatically.
using (DataReader reader1 = cmd1.ExecuteReader()) {
....
while (reader1.Read()) {
....
using (DataReader reader3 = cmd4.ExecuteReader()) {
while (reader3.Read()) {
}
} //reader3 is closed here automatically
}
} //reader1 is closed here automatically
Furthermore, I'm not sure if I remember correctly, but I think it's not possible to have two open readers on the same connection. I may be wrong with this, though.

My primary key is not getting updated

When I tried to update my primary key from the textbox, it's not getting updated. The rest of the columns are updated fine. Please help me.
I am not getting any error. Nothing.. When I try to update the part number.. it's not updating.. Simply going back to the previous value.
My code to update value to database:
private void Update_Click(object sender, EventArgs e)
{
try
{
SqlConnection con = new SqlConnection(#"Data Source=SREEJITHMOHA492\SQLEXPRESS;Initial Catalog=cndb;Integrated Security=True");
con.Open();
SqlCommand cmd = new SqlCommand(#"update cncinfo set part='" + this.file_NameTextBox.Text
+ "',drawings='" + this.drawingsTextBox.Text + "',draftpath='"
+ this.gcodeTextBox.Text + "',comments='" + this.commentsTextBox.Text
+ "' where part='" + dataGridView1.Rows[0].Cells[0].Value.ToString() + "' ;", con);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
void load_table()
{
SqlConnection con = new SqlConnection(#"Data Source=SREEJITHMOHA492\SQLEXPRESS;Initial Catalog=cndb;Integrated Security=True");
con.Open();
SqlCommand cmd = new SqlCommand("select part as 'Part Number',drawings as 'Drawings',draftpath as 'G-Code Path',releasepath as 'Release Path',comments as 'Comments' from cncinfo ;", con);
cmd.ExecuteNonQuery();
con.Close();
try
{
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = cmd;
dbddataset = new DataTable();
sda.Fill(dbddataset);
BindingSource bSource = new BindingSource();
bSource.DataSource = dbddataset;
dataGridView1.DataSource = bSource;
sda.Update(dbddataset);
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Thanks in advance
First, use parameters. See Bobby Tables.
Second, your update statement uses the same input for both the set and where clauses:
#"update cncinfo set part='" + this.file_NameTextBox.Text + "',...' where part='" + this.file_NameTextBox.Text + "' ;"
How do you plan to change the value of the part when you select only the row that already has the new value? You need to use both an old and new value:
#"update cncinfo set part='" + this.file_NameTextBox.Text + "',...' where part='" + oldPart + "' ;"
Finally, ExecuteNonQuery returns the number of rows affected. If you checked the value you would find that it is 1 when you update a row and 0 when you try to change the value of part unless there is already a row with the new part value (in which case you update that row instead of generating an error on a duplicate part).
You should also consider using a using statement for your connections and commands.

Need to close the SqlDataReader associated with Command to enable successful login

I'm being presented with the following error message every attempt to login using the correct credentials:
There is already an open DataReader associated with this Command which must be closed first.
Please could someone dissect this code so I can finally move onto the next phase, thanks people!
// Login Function for Manual Login
public void ent()
{
try
{
SqlConnection con = new SqlConnection(cc.connectDB());
con.Open();
SqlCommand cmd = new SqlCommand("delete from log", con);
cmd.ExecuteNonQuery();
SqlCommand cmd1 = new SqlCommand("select * from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
cmd1.ExecuteNonQuery();
SqlDataReader c = cmd1.ExecuteReader();
if (c.Read() == true)
{
SqlCommand cmd2 = new SqlCommand("select typeid from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
Int32 count = (Int32)cmd2.ExecuteScalar();
if (count == 1)
{
SqlCommand cmd3 = new SqlCommand("insert into log values ('" + 1 + "')", con);
cmd3.ExecuteNonQuery();
}
else
if (count == 2)
{
SqlCommand cmd3 = new SqlCommand("insert into log values ('" + 2 + "')", con);
cmd3.ExecuteNonQuery();
}
Menu shw = new Menu();
shw.Show();
this.Hide();
}
else
{
MessageBox.Show("Login failed");
}
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
}
I'm connecting to an SQL Express server that is fully up and running but I just can't seem to find a way in which I'm able to close the reader without causing unnecessary errors.
You are executing select on the same table (dbo.LOGIN) twice without closing the reader before the second execution
Instead of following line
SqlCommand cmd2 = new SqlCommand("select typeid from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
Int32 count = (Int32)cmd2.ExecuteScalar();
You can read typeid as
INT32 count = Convert.ToInt32(c["typeid"].ToString());
Also it is recommended to dispose connection, command and reader objects otherwise you will run into some error sooner or later
For example
using(SqlConnection con = new SqlConnection(cc.connectDB())
{
con.Open();
using(SqlCommand cmd = new SqlCommand("delete from log", con))
{
cmd.ExecuteNonQuery();
}
using(SqlCommand cmd1 = new SqlCommand("select * from Login where username='" + username.Text + "' and password='" + password.Text + "'", con))
{
//You don't need this
//cmd1.ExecuteNonQuery();
using(SqlDataReader c = cmd1.ExecuteReader())
{
//You don't need these lines - this is probably the line of error
//SqlCommand cmd2 = new SqlCommand("select typeid from Login where username='" + username.Text + "' and password='" + password.Text + "'", con);
//Int32 count = (Int32)cmd2.ExecuteScalar();
INT32 count = Convert.ToInt32(c["typeid"].ToString());
//other sruffs
}
}
}
The problem likely originates here, i.e. you should not be calling to an extraneous cmd1.ExecuteNonQuery(); before you invoke cmd1.ExecuteReader():
cmd1.ExecuteNonQuery(); <-- This is redundant, and possibly harmful
SqlDataReader c = cmd1.ExecuteReader(); <-- Just do this.
You just need the call to cmd1.ExecuteReader
However, that said, there are a lot of unclosed / undisposed resources in your code. You should be disposing of connections, commands and readers, e.g. use using:
using (var cmd = new SqlCommand("delete from log", con))
{
cmd.ExecuteNonQuery();
}
Edit
Where? Like so. And you'll also want to parameterize your queries. Note that you can stack up your usings to prevent a crazy amount of nesting:
var someMessageToShowToUser = "";
try
{
using (var con = new SqlConnection(cc.connectDB()))
using (var cmd = new SqlCommand("delete from log", con))
using (var cmd1 = new SqlCommand(
"select * from Login where username=#UserName and password=#Password", con))
{
con.Open();
cmd.ExecuteNonQuery();
cmd1.Parameters.AddWithValue("#UserName", username.Text);
cmd1.Parameters.AddWithValue("#Password", password.Text);
// cmd1.ExecuteNonQuery(); -> Delete this line.
using (var c = cmd1.ExecuteReader())
{
if (c.Read() == true)
{
using (var cmd2 = new SqlCommand("Parameterize me too")
{
var count = (Int32) cmd2.ExecuteScalar();
if (count == 1)
{
using (var cmd3 = new SqlCommand("insert into log values (#AnotherParam)", con))
{
cmd3.ExecuteNonQuery();
}
}
else if (count == 2)
{
using (var cmd3 = new SqlCommand("insert into log values (#AnotherParam)", con))
{
cmd3.ExecuteNonQuery();
}
}
Menu shw = new Menu();
shw.Show();
this.Hide();
}
}
else
{
someMessageToShowToUser = "Login failed";
}
}
}
}
catch (Exception ee)
{
someMessageToShowToUser = ee.Message;
}
MessageBox.Show(someMessageToShowToUser);
I guess another point is it isn't a good idea to show MessageBoxes (waiting for user to click buttons) while you've got open connections to the database. Ideally you'll want to separate your data access code from your presentation code (and possibly further separations as well).

Want to create a comment system in asp.net

i am coding for a commenting system in asp.net C# but i am stopped at delete command because of i am not using any type of serial numbers to comments posted, then how can i able to delete a specific comment, i am just using a username, date, time, and text in comment. Can anyone help me please that how to use a delete command in this condition??
here is my code for posting:
protected void pospost_Click(object sender, EventArgs e)
{
string login;
if (HttpContext.Current.Session["UserName"] != null)
{
login = HttpContext.Current.Session["UserName"].ToString();
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.CommandText = "select * from mobiles_pos";
da = new SqlDataAdapter(cmd);
ds = new DataSet();
da.Fill(ds);
DataRow rw = ds.Tables[0].NewRow();
rw[0] = Model.Text.ToString();
rw[1] = titlepos.Text.ToString();
rw[2] = txtpos.Text.ToString();
rw[3] = DateTime.Today.Date.ToString();
rw[4] = DateTime.Now.TimeOfDay.ToString();
rw[5] = login.ToString();
ds.Tables[0].Rows.Add(rw);
SqlCommand cmd1 = new SqlCommand();
cmd1.Connection = con;
cmd1.CommandText = "insert into mobiles_pos values('" + Model.Text + "','" + titlepos.Text + "','" + txtpos.Text + "','" + DateTime.Today.Date + "','" + DateTime.Now.TimeOfDay + "','" + login + "')";
da.InsertCommand = cmd1;
da.Update(ds);
con.Close();
titlepos.Text = "";
txtpos.Text = "";
//DataList2.DataSource = ds;
//DataList2.DataBind();
BindDataList2();
}
}
Best - Add a Primary key to the "mobiles_pos" table since your using sql just use an identity field it will auto increment for you.
or
Quick - Use a combination of the User name and date comment was intered you must use the full date time or it will delete everything that user entered that day.
"Delete from mobiles_pos where username = #UserName and createdDate = #createdDate"

Categories