In my c# application i am trying to delete a record and i am returning result of the executenonquery to check the deletion is exactly happening as below.
rowsAffected = db.ExecuteNonQuerySQL(
#"DELETE FROM relation WHERE parent_itemid = " + SourceThingId + " AND " +
" child_itemid = " + ThingId + " AND " +
" relation_typeid = " + RelationTypeId);
And the executenonquery is definesd as below,
using (SQLiteTransaction dbtrans = conn.BeginTransaction())
{
SQLiteCommand cmd = conn.CreateCommand();
cmd.CommandText = sqlExpr;
cmd.CommandType = CommandType.Text;
ireturn = cmd.ExecuteNonQuery();
dbtrans.Commit();
}
return ireturn;
But when i am executing its not deleting and the value returns 0.The databse used is sqlite.
Do any one have idea why it happens.Please help.
Thanx in advance.
Well it certainly sounds like the record simply isn't there. You should debug this by running a SELECT * with the same query, and see whether you get any results back.
You should also stop putting your values directly into SQL, and instead use parameterized SQL. That will give a better separation of code and data, avoid SQL injection attacks, and avoid conversion issues (particularly with date/time values).
Related
I have a query to insert a row into a table, which has a field called ID, which is populated using an AUTO_INCREMENT on the column. I need to get this value for the next bit of functionality, but when I run the following, it always returns 0 even though the actual value is not 0:
MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertInvoice;
comm.CommandText += "\'" + invoiceDate.ToString("yyyy:MM:dd hh:mm:ss") + "\', " + bookFee + ", " + adminFee + ", " + totalFee + ", " + customerID + ")";
int id = Convert.ToInt32(comm.ExecuteScalar());
According to my understanding, this should return the ID column, but it just returns 0 every time. Any ideas?
EDIT:
When I run:
"INSERT INTO INVOICE (INVOICE_DATE, BOOK_FEE, ADMIN_FEE, TOTAL_FEE, CUSTOMER_ID) VALUES ('2009:01:01 10:21:12', 50, 7, 57, 2134);last_insert_id();"
I get:
{"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 'last_insert_id()' at line 1"}
MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertStatement; // Set the insert statement
comm.ExecuteNonQuery(); // Execute the command
long id = comm.LastInsertedId; // Get the ID of the inserted item
[Edit: added "select" before references to last_insert_id()]
What about running "select last_insert_id();" after your insert?
MySqlCommand comm = connect.CreateCommand();
comm.CommandText = insertInvoice;
comm.CommandText += "\'" + invoiceDate.ToString("yyyy:MM:dd hh:mm:ss") + "\', "
+ bookFee + ", " + adminFee + ", " + totalFee + ", " + customerID + ");";
+ "select last_insert_id();"
int id = Convert.ToInt32(comm.ExecuteScalar());
Edit: As duffymo mentioned, you really would be well served using parameterized queries like this.
Edit: Until you switch over to a parameterized version, you might find peace with string.Format:
comm.CommandText = string.Format("{0} '{1}', {2}, {3}, {4}, {5}); select last_insert_id();",
insertInvoice, invoiceDate.ToString(...), bookFee, adminFee, totalFee, customerID);
Use LastInsertedId.
View my suggestion with example here: http://livshitz.wordpress.com/2011/10/28/returning-last-inserted-id-in-c-using-mysql-db-provider/
It bothers me to see anybody taking a Date and storing it in a database as a String. Why not have the column type reflect reality?
I'm also surprised to see a SQL query being built up using string concatenation. I'm a Java developer, and I don't know C# at all, but I'd wonder if there wasn't a binding mechanism along the lines of java.sql.PreparedStatement somewhere in the library? It's recommended for guarding against SQL injection attacks. Another benefit is possible performance benefits, because the SQL can be parsed, verified, cached once, and reused.
Actually, the ExecuteScalar method returns the first column of the first row of the DataSet being returned. In your case, you're only doing an Insert, you're not actually querying any data. You need to query the scope_identity() after you're insert (that's the syntax for SQL Server) and then you'll have your answer. See here:
Linkage
EDIT: As Michael Haren pointed out, you mentioned in your tag you're using MySql, use last_insert_id(); instead of scope_identity();
I wrote that to update my SQL table.
mycmd.CommandText = "UPDATE savedinfo SET User_id='" + Login.GetUserID().ToString() + "', Date='" + DateTime.Now.ToLongDateString() + "', Evaluate='" + activeEvaluate.ToString() + "', TimeStart='" + dtCurrentTime1.ToLongTimeString() + "', TimeEnd='" +dtCurrentTime2.ToLongTimeString() + "' , Salary= '" + todaySalary.Text +"'";
mycmd.Connection = con;
mycmd.ExecuteNonQuery();
When getting to mycmd.ExecuteNonQuery(); I got an error:
An unhandled exception of type 'System.Data.SqlClient.SqlException'
occurred in System.Data.dll
Additional information: String or binary data would be truncated.
The statement has been terminated.
What is the problem here?
Thanks
The error implies that you are attempting to insert a value which is to big for the column length within the database. Please look through your database schema and identify which column is causing the issue.
Looking at the snippet of code I have a few other observations which maybe of some help.
Does the Update statement require a where clause?
Do use parameterised queries as this will help against SQL injection attacks.
Using statement are very helpful in clearing and cleaning up an objects, in this case a using statement help managing the open connections to the database.
If you wish to check for valid string lengths before sending them to the database check the arguments before creating connections etc. ideally these check would be carried out in your business logic layer.
if (activeEvaluate.Length > 5)
{
throw new ArgumentException("activeEvaluate");
}
using (SqlConnection connection = new SqlConnection(ConnString))
{
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "UPDATE savedinfo set User_id= #UserId, Date = #Date, Evaluate = #Evaluate, TimeStart = #TimeStart, TimeEnd = #TimeEnd, Salary = #Salary ";
cmd.Parameters.AddWithValue("#UserId", Login.GetUserID());
cmd.Parameters.AddWithValue("#Date", DateTime.Now.ToLongDateString());
cmd.Parameters.AddWithValue("#Evaluate", activeEvaluate.ToString());
cmd.Parameters.AddWithValue("#TimeStart", dtCurrentTime1.ToLongTimeString());
cmd.Parameters.AddWithValue("#TimeEnd", dtCurrentTime2.ToLongTimeString());
cmd.Parameters.AddWithValue("#Salary", todaySalary.Text);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
datetime=Datetime.Now;
string strquery = #"INSERT INT0 [Destination_CMS].[dbo].[Destination_CMS_User]
values('" + userid + "','" + email + "','"
+ userType + "','" + userStatus + "','" + processed + "','"
+ datetime.ToLongDateString() + "')";
cmd = new SqlCommand(strquery, con);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
I am getting error:
Incorrect syntax near 'Destination_CMS'.
You've written INT0 rather than INTO.
Also, use parameterized queries.
You should try to change INT0 to INTO.
INSERT INT0 [Destination_CMS].[dbo]
I think its INSERT INTO rather than INT0 (zero)
Print the query to the screen, and verify where the syntax error is.
Next to that; use parametrized queries, like this:
string query = "INSERT INTO [tablename] ( column, column ) VALUES (#p_param1, #p_param2)";
var command = new SqlCommand (query);
command.Parameters.Add ("#p_param1", SqlDbType.DateTime).Value = DateTime.Now;
...
You are risking sql injection, if not using parametrized queries..
Your problem looks solved, so my next question would be, why not use an ORM like NHibernate/EF etc.., depending on your requirements offocourse, but ADO.NET plumbing in my books is where performance is an absolute issue.
You could write this as a stored procedure instead, which has the advantage of making typos like this a lot easier to spot and fix.
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'
I've got a error which I can't understand. When I'm debugging and trying to run a insert statement, its throwing the following exception:
"There are fewer columns in the INSERT statement than values specified in the VALUES clause. The number of values in the VALUES clause must match the number of columns specified in the INSERT statement."
I have looked all over my code, and I can't find the mistake I've made.
This is the query and the surrounding code:
SqlConnection myCon = DBcon.getInstance().conn();
int id = gm.GetID("SELECT ListID from Indkøbsliste");
id++;
Console.WriteLine("LNr: " + listnr);
string streg = GetStregkode(navne);
Console.WriteLine("stregk :" + strege);
string navn = GetVareNavn(strege);
Console.WriteLine("navn :" + navne);
myCon.Open();
string query = "INSERT INTO Indkøbsliste (ListID, ListeNr, Stregkode, Navn, Antal, Pris) Values(" + id + "," + listnr + ", '" + strege + "','" + navn + "'," + il.Antal + ", "+il.Pris+")";
Console.WriteLine(il.Antal+" Antal");
Console.WriteLine(il.Pris+" Pris");
Console.WriteLine(id + " ID");
SqlCommand com = new SqlCommand(query, myCon);
com.ExecuteNonQuery();
com.Dispose();
myCon.Close();
First of all check the connection string and confirm the database location and number of columns a table has.
Suggestion : Do not use hardcoded SQL string. Use parameterized sql statements or stored-proc.
Try parameterized way,
string query = "INSERT INTO Indkøbsliste (ListID, ListeNr, Stregkode, Navn, Antal, Pris)
Values (#ListID, #ListeNr, #Stregkode, #Navn, #Antal, #Pris)"
SqlCommand com = new SqlCommand(query, myCon);
com.Parameters.Add("#ListID",System.Data.SqlDbType.Int).Value=id;
com.Parameters.Add("#ListeNr",System.Data.SqlDbType.Int).Value=listnr;
com.Parameters.Add("#Stregkode",System.Data.SqlDbType.VarChar).Value=strege ;
com.Parameters.Add("#Navn",System.Data.SqlDbType.VarChar).Value=navn ;
com.Parameters.Add("#Antal",System.Data.SqlDbType.Int).Value=il.Antal;
com.Parameters.Add("#Pris",System.Data.SqlDbType.Int).Value=il.Pris;
com.ExecuteNonQuery();
Please always use parametrized queries. This helps with errors like the one you have, and far more important protects against SQL injection (google the term, or check this blog entry - as an example).
For example, what are the actual values of strege and/or navn. Depending on that it may render your SQL statement syntactically invalid or do something worse.
It (looks like) a little more work in the beginning, but will pay off big time in the end.
Are you using danish culture settings?
In that case if il.Pris is a double or decimal it will be printed using comma, which means that your sql will have an extra comma.
Ie:
INSERT INTO Indkøbsliste (ListID, ListeNr, Stregkode, Navn, Antal, Pris) Values(33,5566, 'stegkode','somename',4, 99,44)
where 99,44 is the price.
The solution is to use parameters instead of using the values directly in you sql. See some of the other answers already explaining this.