C# MySQL - "Update" is selecting every row/everything - c#

My issue is that everytime I try to update in my CMS, it simply updates EVERY column / row.
For example:
I update Test 1 -> Test 2
Meanwhile I have Test 4
But then Test 4 -> Test 2 due to I changed Test 1 to 2 it simply changes that aswell.
They still work by ID correctly, and when I delete them, they delete individually, so the only function that is overlapping with everything is update.
I will now post my code (this is what I have learned, do not comment on security or w/e) simply need this issue fixed so it only updates the selected ID row.
First:
public DataRow GetById(string ID)
{
strSQL = "SELECT ID, clnOverskrift, clnTekst "
+ "FROM tblForside "
+ "WHERE ID=#ID";
objCMD = new MySqlCommand(strSQL);
objCMD.Parameters.AddWithValue("#ID", ID);
return objData.GetData(objCMD, objCon).Rows[0];
}
public void Update(PropertyForside Pro)
{
strSQL = "UPDATE tblForside SET "
+ " clnOverskrift=#Overskrift, clnTekst=#Tekst ";
objCMD = new MySqlCommand(strSQL);
objCMD.Parameters.AddWithValue("#Overskrift", Pro.Overskrift);
objCMD.Parameters.AddWithValue("#Tekst", Pro.Tekst);
objData.ModifyData(objCMD, objCon);
}
I will use both GetById and Update thats why I included both.
if you need to know more in this "factory" i will post it.
Here i get it:
FactoryForside fac = new FactoryForside();
PropertyForside Pro = new PropertyForside();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataRow dr = fac.GetById(Request.QueryString["ID"]);
txtOverskrift.InnerText = dr["clnOverskrift"].ToString();
txtText.InnerText = dr["clnTekst"].ToString();
}
}
protected void btnGem_Click(object sender, EventArgs e)
{
Pro.Overskrift = txtOverskrift.InnerText;
Pro.Tekst = txtText.InnerText;
Pro.ID = int.Parse(Request.QueryString["ID"]);
fac.Update(Pro);
Response.Redirect("RedigerForside.aspx");
}
I use InnerText to use TextAreas with NiceEdit.
Adding new ones work, and deleting as mentioned before - only this updating thing not working correctly.
It displays ID correctly "EditForside.aspx?id=13" in the browser, but it seems to select every other ID aswell
Hope you can help me.

Your UPDATE statement has to include a WHERE condition - the same you use in your select. Then it will update only that particular row. Without a WHERE it updates every row in the table.
Documentation: http://dev.mysql.com/doc/refman/5.0/en/update.html

The reason might be because you have not provided the where condition in your update clause. So if you dont provide a where condition in your update statement it would end up updating every row of your table.
Try something like this:
strSQL = "UPDATE tblForside SET "
+ " clnOverskrift=#Overskrift, clnTekst=#Tekst "
+ " WHERE ID=#ID";

You need to provide a WHERE clause in your update statement. E.g.
strSQL = "UPDATE tblForside SET "
+ " clnOverskrift=#Overskrift, clnTekst=#Tekst "
+ " WHERE ID=#ID";
This limits which rows will be updated.

Related

Updating DatagridView with DataGridViewCheckBoxColumn

I would like to update my mySQL table from a DatagridView with DataGridViewCheckBoxColumns and display it back to my forms. However, my current code checks all rows even if only a single CheckBoxColumn has been checked. Checked or unchecked rows should be both updated so I'm not sure if I still have to add condition if DataGridViewCheckBoxColumns are checked.
foreach (DataGridViewRow row in datagridFamMedHistory.Rows)
{
command.Parameters.Clear();
famMedHistorytype = datagridFamMedHistory.Rows[0].Cells["colType"].Value.ToString();
command.CommandText = #"UPDATE familymedhistory SET paternal = #paternal, maternal = #maternal
WHERE patientid = '" + patientid + "' AND type = '" + famMedHistorytype + "'";
command.Parameters.AddWithValue("#paternal", row.Cells["colPaternal"].Value);
command.Parameters.AddWithValue("#maternal", row.Cells["colMaternal"].Value);
connect.Open();
command.ExecuteNonQuery();
connect.Close();
}
I think I'm missing something, but I can't seem to figured it out.
did you debugged your code?
You are still selecting row 0 in your loop
change :
famMedHistorytype = datagridFamMedHistory.Rows[0].Cells["colType"].Value.ToString();
to :
famMedHistorytype = row.Cells["Column1"].Value.ToString();
Also As collegue wrote in comment, do not open and close connection in loop.. my eyes are bleeding

I want to insert data into the DB automatically after filled a row in datagridview

I bound my DataGridView with a DataBase file. I want to save each and every row to the database after I finish entering values into that row.
I know how to save the complete table but not every row.
The single row that I enter, I want it to save automatically to the DB after I enter a value in last cell of that row and move to the next row.
I wrote some code but not saving but displaying message "record Saved".
Blow my code
private void dataGridView1_RowLeave(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 5)
{
SqlDataAdapter da = new SqlDataAdapter("insert into invtempdb (fullname, quantity, itmbyp, itmprimary, itmtotal) values( '" + dataGridView1.CurrentRow.Cells[1] + "', '" + dataGridView1.CurrentRow.Cells[2] + "','" + dataGridView1.CurrentRow.Cells[3] + "','" + dataGridView1.CurrentRow.Cells[4] + "','" + dataGridView1.CurrentRow.Cells[5] + "')", con);
MessageBox.Show("value saved");
}
else
{
return;
}
Okay, from what I've understood of your question, you need to update the database as soon as you complete filling a row.
You can do that in this way:
The DataGridView has many different events available for usage:
RowLeave
RowsAdded
RowsRemoved
And many more, I think for your exact requirement these three events should be enough.
What you've to do is, put the sql command to update the DataBase inside the event RowLeave. This will update the DataBase everytime you leave the last cell of a particular row.
Read more about the events in their descriptions to find the best suitor for your purpose, but, this is the way to proceed further.
Extension:
I can't see where you've used the RowLeave event, but here's a solution.
SqlConnection con = new SqlConnection(connection string); //put your connection string there
SqlCommand insert = new SqlCommand("insert into invtempdb (fullname, quantity, itmbyp, itmprimary, itmtotal) values(#a,#b,#c,#d,#e);", con)
insert.Parameters.Add("#a",dataGridView1.CurrentRow.Cells[1] );
insert.Parameters.Add("#b",dataGridView1.CurrentRow.Cells[2] );
insert.Parameters.Add("#c",dataGridView1.CurrentRow.Cells[3] );
insert.Parameters.Add("#d",dataGridView1.CurrentRow.Cells[4] );
insert.Parameters.Add("#e",dataGridView1.CurrentRow.Cells[5] );
insert.ExecuteNonQuery();
Put this code inside your event and you're good to go. Your basics are very weak, focus on that else you'll always be stuck on very small errors.

How do I make my query more precise based on my condition to return a string to check duplicate record exist

I am creating string function which checks duplicate record before inserting or updating a record but I have a condition with it. Before giving conditions, I have a table called Products (name, description, type, isActive, InsertedDate, UpdatedDate). Isenabled is in bit datatype (0 or 1). And InsertedDate, UpdatedDate are auto generated.
In isActive column
0 means disable
1 means enable
Before inserting (or even updating), check whether name is unique but if name exist more than one then,
My conditions
Check whether product is isActive = 1 then while inserting data should display message "Product exist in the table."
Check whether product is isActive = 0 then while inserting data should display message "Product exist but it is disabled."
Else Insert/Update the data.
Below function only check whether record exist or not and return message accordingly.
Question: How can I have return proper message regardless I am checking above query for inserting or updating a record and it goes over my requirement. As Top 1 can help me to insert new record checking if name is unique and it will return empty but if I am updating row with its own keeping name as it is and changing other column which is description. And when I update that I am receiving message "Record exist in the table" which it should not give me and should updating without message. So how can I make this query check for both the method inserting and updating record.
Here is what I have tried:
private string GetName(string name, int id)
{
using (var connection = connection string)
using (var command = new SqlCommand())
{
command.Connection = connection;
command.CommandText =
#"DECLARE #Enabled INT; " +
#"SET #Enabled = " +
#"( " +
#"SELECT TOP 2 p.isActive " +
#"FROM dbo.[product] p WITH (nolock) " +
#"WHERE p.name = #name " +
#"); " +
#"SELECT Msg = CONVERT( VARCHAR(32), " +
#"CASE " +
#"WHEN #Enabled = 0 " +
#"THEN 'Record is disabled' " +
#"WHEN #Enabled = 2 " +
#"THEN 'Record exist in the table' " +
#"ELSE ''";
#"END);";
command.Parameters.AddWithValue("name", name);
command.CommandTimeout = 100;
connection.Open();
command.ExecuteNonQuery();
string message = (string)command.ExecuteScalar();
connection.Close();
return message;
}
}
return string.Empty;
}
Note My query might be wrong. If you do not understand my query then please go over to what I am doing before inserting or updating record and accordingly I am expecting to have a query. Also please don't worry about Insert or update query I have a different method which takes care of it. Also if you have any solution which can help me to solve my probkem ten I would really appreciate that.
Summery
First check duplicate record exist or not (Means check all names are unique).
If name exist more than 1 then check isActive is 0 or 1 and accordingly sends the message which I am showing in my query.
FYI: I know I can do it in Stored Procedure but this is like a requirement to do it with command parameter.
Also if you guys think tha this post does not have consistant, please let me know instead of downgrading or flagging it.

Save listbox items in database after ordering

I have an asp.net page with two listboxes and a save button. The user needs to transfer items from listbox1 to listbox2 according to his order I mean that user can choose witch item come in the first place and which come next.
After that my system suggest the results (most commonly) that achieve the ordered items, I hope you understand
I did the transfer method between the two listboxes and it work good. But I'm stuck in the save method, it can save the items after being in listbox2 but not in the same order of transferring (user order).
Here is my code for save button:
protected void Button1_Click(object sender, EventArgs e)
{
string strConnString = ConfigurationManager.ConnectionStrings["ConnectionString2"].ConnectionString;
string str;
OracleCommand com;
OracleConnection con = new OracleConnection(strConnString);
try
{
con.Open();
for (int i = 0; i < ListBox2.Items.Count; i++)
{
str = "insert into Criteria values('" + ListBox2.Items[i].ToString() + "')";
com = new OracleCommand(str, con);
com.ExecuteNonQuery();
}
LabOut.Visible = true;
LabOut.Text = "Upload succesful!";
con.Close();
//Response.Write("Inserted");
}
catch (Exception)
{
LabOut.Visible = true;
LabOut.Text = "Upload failed!";
}
finally
{
con.Close();
con.Dispose();
}
}
The problem here is that database tables do not inherently have a concept of order. Retrieving rows from a table never guarantees an order unless you use a order by clause.
You should add an additional column to your table (named, for example, "Sequence" or "Order"). It can be an int or some other sortable value. You would then need to modify your insert statement:
str = "insert into Criteria(ItemValue, Sequence) values('" + ListBox2.Items[i].ToString() + "'," + i.ToString() + ")";
and retrieve the list using
str = "Select ItemValue from Criteria order by Sequence"
#fifo follow me
1st add a column in your database say it is SeqNo.
Then save your data with that. I mean generate SeqNo. for each listbox2 item and save it.
When you will fetch data from database into lintbox2 then use sql/linq ORDER BY on SeqNo. column and display them on which Order that you were saved. Simple.. :)

SQL Update - Not updating multiple rows in a for loop

I have a DataGridView(DGV) linked to a SQlite database. I want to update some info on the DGV. So, I have a context menu that lets me change one column and update the DB as well. I want to have the ability to select multiple rows and edit as well. For ex: if i select five rows and change the type from alarms to errors ; the change is reflected in the DGV and then when i look into the database , the change isnt reflected. Only one row is updated.
My code snippet is below
foreach (DataGridViewRow r in dataGridView1.SelectedRows)
{
SQLiteTransaction SQLiteTrans = connection.BeginTransaction();
SQLiteCommand cmd = connection.CreateCommand();
MessageBox.Show(r.ToString());
if (r.Cells["typeDataGridViewTextBoxColumn"].Value.ToString().Contains("#") == false)
{
r.Cells["typeDataGridViewTextBoxColumn"].Value = r.Cells["typeDataGridViewTextBoxColumn"].Value.ToString() + " # " + max;
}
else
{
r.Cells["typeDataGridViewTextBoxColumn"].Value = r.Cells["typeDataGridViewTextBoxColumn"].Value.ToString().Substring(0, r.Cells["typeDataGridViewTextBoxColumn"].Value.ToString().IndexOf("#")) + "# " + max;
}
string querytext = "Update LogDatabase set Type = \"" + r.Cells["typeDataGridViewTextBoxColumn"].Value + "\" where HashKey = \"" + r.Cells["hashKeyDataGridViewTextBoxColumn"].Value.ToString() + "\"";
cmd.CommandText = querytext;
cmd.ExecuteNonQuery();
SQLiteTrans.Commit();
}
I dont have too much experience with SQL. So, im not sure if something is wrong with how ive updated the database!
What do i have to edit to make sure all the rows are updated in the DB as well?!
Help appreciated.
Edit: Tried checking the query before its sent.
When i try editing multiple rows in the DGV without sorting the DGV under any column it works and updates all the rows simultaneously... But When I try to sort them based on "Type" and then edit the rows, the same query is passed ! :| (Hash Key doesnt change)
Its like, the one row keeps moving up the list of rows and is always the row r in the for loop.
Edit 2: Its definitely a problem with the rows of the DGV
Everytime I sort the DGV and then try to edit the fields, the queries have hashkey values different from the once that i selected. Its like the row ids are changed completely after one update. It looks like the DGV automatically sorts once one row is updated !
Is there a way to disable this???!
It looks like you weren't increasing max counter.
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
using (SQLiteTransaction SQLiteTrans = connection.BeginTransaction())
{
SQLiteCommand cmd = connection.CreateCommand();
MessageBox.Show(row.ToString());
var txtValue = row.Cells["typeDataGridViewTextBoxColumn"].Value;
if (txtValue.Contains("#"))
{
txtValue = String.Format("{0} # {1}", txtValue, max);
}else
{
txtValue = txtValue.SubString(0, txtValue.IndexOf("#")) + "# " + max.ToString();
}
string querytext = "Update LogDatabase set Type = #type where HashKey = #key";
//Create your SqlParameters here!
cmd.CommandText = querytext;
cmd.ExecuteNonQuery();
SQLiteTrans.Commit();
max++; //You weren't increasing your counter!!
}
}
Your problem is that you are using double quotes in your SQL query to delimit your string values. Replace them for single quotes:
string querytext = "Update LogDatabase set Type = '" +
r.Cells["typeDataGridViewTextBoxColumn"].Value +
"' where HashKey = '" +
r.Cells["hashKeyDataGridViewTextBoxColumn"].Value.ToString() +
"'";
Also, beware of SQL Injection. Your code is not dealing with that.

Categories

Resources