Update ExceptionNonQuery - c#

I am trying to update an MS Access table and it keeps throwing an error:
An unhandled exception of type 'System.Data.OleDb.OleDbException' occurred in System.Data.dll
Additional information: Syntax error in string in query expression 'EmID = '234'.
The EmID is in the database. Please help
public partial class Sales : Form
{
...
private void btnUpdate_Click(object sender, EventArgs e)
{
int EmpID = int.Parse(txtEmpID.Text);
OleDbConnection con = new OleDbConnection(#"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\\SalesData.mdb");
OleDbCommand update = new OleDbCommand("UPDATE Sales SET Printer = '" + txtPrinter.Text + "', Ink = '" +txtInk.Text + "', Paper = '"+txtPaper.Text+"' WHERE EmID = '" + txtEmpID.Text + " ", con);
con.Open();
update.ExecuteNonQuery();
con.Close();
MessageBox.Show("Sales Updated");
}
...
}

You have forgotten to add a closing quote after the WHERE value. But fixing the problem adding the missing quote serves only to hide other problems.
What if one of your textboxes contains a single quote? You will get again a syntax error exception caused by the string concatenation where the quotes serve as delimiter of your values. With a single quote typed by your user you will confuse the Sql Parser again.
To fix this problem (and a more serious one called Sql Injection) you need to start using parameters
string cmdText = #"UPDATE Sales SET Printer = #printer,
Ink = #Ink, Paper = #Paper
WHERE EmID = #id";
using(OleDbConnection con = new OleDbConnection(...))
using(OleDbCommand cmd = new OleDbCommand(cmdText, con))
{
con.Open();
cmd.Parameters.Add("#printer", OleDbType.VarWChar).Value = txtPrinter.Text;
cmd.Parameters.Add("#ink", OleDbType.VarWChar).Value = txtInk.Text;
cmd.Parameters.Add("#paper", OleDbType.VarWChar).Value = txtPaper.Text;
cmd.Parameters.Add("#id", OleDbType.VarWChar).Value = txtEmpID.Text;
cmd.ExecuteNonQuery();
}

Related

Updating my database won't work because of incorrect syntax for MySql

I am trying to update my database but then this error about my syntax shows up
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 '(platenumber,brand,model,yearmodel,regdate,exdate,odometer) set id = '1' values(' at line 1'
I am not too familiar with MySQl but I got rid of all the errors it showed here in my code
private void savebtn_Click(object sender, EventArgs e)
{
string ID = idtxt.Text;
MySqlCommand cmd = new MySqlCommand("update inventory.vehicle(platenumber,brand,model,yearmodel,regdate,exdate,odometer) set id = '" + this.idtxt.Text + "' values(#platenumber, #brand, #model,#yearmodel, #regdate, #exdate,#odometer) where id = '"+ this.idtxt.Text +"'", conn);
cmd.Parameters.Add("#platenumber", MySqlDbType.VarChar, 10).Value = pnumber.Text;
cmd.Parameters.Add("#brand", MySqlDbType.VarChar, 60).Value = brand.Text;
cmd.Parameters.Add("#model", MySqlDbType.VarChar, 45).Value = model.Text;
cmd.Parameters.Add("#yearmodel", MySqlDbType.Int32).Value = yearmodel.Text;
cmd.Parameters.Add("#regdate", MySqlDbType.Date).Value = datereg.MinDate;
cmd.Parameters.Add("#exdate", MySqlDbType.Date).Value = regexp.MinDate;
cmd.Parameters.Add("#odometer", MySqlDbType.Decimal).Value = odometer.Text;
int i = cmd.ExecuteNonQuery();
if (i != 0)
{
MessageBox.Show("Success");
}
else
{
MessageBox.Show("Fail");
}
this.Close();
}
what could be causing this error?
As stated in the error, your query is wrong
MySqlCommand cmd = new MySqlCommand(
"update inventory.vehicle
(platenumber,brand,model,yearmodel,regdate,exdate,odometer)
set id = '" + this.idtxt.Text + "'
values(#platenumber, #brand, #model,#yearmodel, #regdate, #exdate,#odometer)
where id = '"+ this.idtxt.Text +"'", conn);
mustn't have values part and should look like
UPDATE inventory.vehicle SET
platenumber=#platenumber,
brand=#brand
model=#model,
....
WHERE id = #id
Don't ever use string join inside a query, but use parameters instead for two main reasons:
You don't go crazy combining strings
Your query won't suffer for SQL injection
So even WHERE id= part must use a parameter!
You have problem in the query, the UPDATE statement should be in this format.
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;

Is there a way to make this code insert all the current data in the database?

What i want is to insert all of the data in all rows and columns from my datagrid view into my database. I am not getting any error but this is not working not inserting any value in my database.
con.Open();
SqlCommand cmd = new SqlCommand();
cmd = con.CreateCommand();
for (int i = 0; i < dgEdit.Rows.Count; i++)
{
DateTime ds = DateTime.Now;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "INSERT INTO Tb BL_Attendance(Course, Subject,
Year, Section, Name, Room, SeatNo, Status, Date) VALUES('" +
dgvAtt.Rows[i].Cells[0].Value + "', '" +
dgvAtt.Rows[i].Cells[1].Value + "', '" +
dgvAtt.Rows[i].Cells[2].Value + "', '" +
dgvAtt.Rows[i].Cells[3].Value + "', '" +
dgvAtt.Rows[i].Cells[4].Value + "', '" +
dgvAtt.Rows[i].Cells[5].Value + "', '" +
dgvAtt.Rows[i].Cells[6].Value + "', '" +
dgvAtt.Rows[i].Cells[7].Value + "', #Date) ";
cmd.Parameters.AddWithValue("#Date", ds);
cmd.ExecuteNonQuery();
}
MessageBox.Show("Updated! please check the report", "Save",
MessageBoxButtons.OK, MessageBoxIcon.Information);
con.Close();
I was expecting this to insert all of my datagrid values into a table
The logic below tries to be as close as possible to your implementation, but taking into account best practices when dealing with database connections:
// You will need the following namespaces:
// using System;
// using System.Data;
// using System.Data.SqlClient;
// using System.Windows.Forms;
var connectionString = "Your SQL Server connection string";
using (var con = new SqlConnection(connectionString))
{
con.Open();
var cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText =
"INSERT INTO Tbl_Attendance (Course, Subject, Year, Section, Name, Room, SeatNo, Status, Date) " +
"VALUES (#Course, #Subject, #Year, #Section, #Name, #Room, #SeatNo, #Status, #Date)";
var courseParam = cmd.Parameters.Add("#Course", SqlDbType.VarChar, 50);
var subjectParam = cmd.Parameters.Add("#Subject", SqlDbType.VarChar, 50);
var yearParam = cmd.Parameters.Add("#Year", SqlDbType.VarChar, 50);
var sectionParam = cmd.Parameters.Add("#Section", SqlDbType.VarChar, 50);
var nameParam = cmd.Parameters.Add("#Name", SqlDbType.VarChar, 50);
var roomParam = cmd.Parameters.Add("#Room", SqlDbType.VarChar, 50);
var seatNoParam = cmd.Parameters.Add("#SeatNo", SqlDbType.VarChar, 50);
var statusParam = cmd.Parameters.Add("#Status", SqlDbType.VarChar, 50);
var dateParam = cmd.Parameters.Add("#Date", SqlDbType.DateTime);
dateParam.Value = DateTime.Now;
// If you are going to insert a lot of records, it's advised to call the Prepare method on your SqlCommand.
// Un-comment the line below if you want to see how this behaves.
// cmd.Prepare();
foreach (DataGridViewRow row in dgEdit.Rows)
{
courseParam.Value = row.Cells[0].Value;
subjectParam.Value = row.Cells[1].Value;
yearParam.Value = row.Cells[2].Value;
sectionParam.Value = row.Cells[3].Value;
nameParam.Value = row.Cells[4].Value;
roomParam.Value = row.Cells[5].Value;
seatNoParam.Value = row.Cells[6].Value;
statusParam.Value = row.Cells[7].Value;
cmd.ExecuteNonQuery();
}
}
MessageBox.Show("Updated! please check the report", "Save", MessageBoxButtons.OK, MessageBoxIcon.Information);
Reason behind the changes:
When possible, instantiate and open your SqlConnection connection inside a
using statement. This will ensure that your connection is always
closed (disposed) when you are done with it in the scope.
Always use parameters in your queries when interacting with any external input, to avoid Bobby's mom exploit! (https://xkcd.com/327/).
This will ensure that your code is not susceptible to SQL injection.
As you can see, I added some parameters, but because you didn't
provide your table schema I made then VARCHAR(50) with the
exception of the #Date one where it's clear that you are saving a
System.DateTime. Please feel free to change the SqlDbType.VarChar
to the correct type where needed.
I moved the call to MessageBox.Show outside the using scope so it doesn't interfere with the connection disposal.
Another enhancement that you could do to this logic is implementing the use of the System.Transactions.TransactionScope class (you must add a reference to System.Transactions.dll), to ensure that if there's an error during any of the inserts, nothing gets committed to the database.
Your prototype is correct but you did one mistake, dgvAtt.Rows[i].Cells[0].Value return an Object to must convert it to ToString() or the column data in your table that could match with.
Let's say this is my form
I Created a table 'Person'
Code Source
private void button1_Click(object sender, EventArgs e)
{
try
{
SqlCommand cmd = new SqlCommand();
cmd = con.CreateCommand();
for (int i = 0; i < dgvAtt.Rows.Count - 1; i++)
{
con.Open();
cmd.CommandType = CommandType.Text;
string Query = "INSERT INTO Person (idPerson, fullnamePerson) VALUES (" + dgvAtt.Rows[i].Cells[0].Value.ToString() + ",'" + dgvAtt.Rows[i].Cells[1].Value.ToString() + "')";
cmd.CommandText = Query;
cmd.ExecuteNonQuery();
con.Close();
}
MessageBox.Show("Updated! please check the report", "Save", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Don't write any Parameters because this will give you an exception.

Select password field and show it in textbox by criteria

I have a windows form with 4 textbox fields: username, question, date of birth, and password.
I want to load and display the password from the database table if the entered informations are correct (username, question and dateOfBirth textbox) and the OK button is pressed.
SqlConnection myConn = new SqlConnection(myConnection);
SqlCommand SelectCommand = new SqlCommand("select PassWord from dbo.Admin where UserName = '" + this.UserName.Text + "' and Question= '" + this.Question.Text + "' and DateOfBirth= '" + this.DateOfBirth.Text + "';", myConn);
SqlDataReader myReader;
myConn.Open();
myReader = SelectCommand.ExecuteReader();
PassShow.Text = myReader["PassWord"].ToString();
myConn.Close();
I use VS 2015, writing this in c# with db from VS.
I have this error when i debug it:
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Data.dll
Additional information: Invalid attempt to read when no data is present.
If you only want to return one row and one column, use this instead:
PassShow.Text = SelectCommand.ExecuteScalar()?.ToString();
Otherwise you have to check if the reader got any result rows before you can access them savely:
using (SqlDataReader myReader = SelectCommand.ExecuteReader())
{
if (myReader.HasRows && myReader.Read())
PassShow.Text = myReader.GetString("PassWord");
}
This worked perfectly for me:
myReader = SelectCommand.ExecuteReader();
if (myReader.HasRows && myReader.Read())
{
PassShow.Text = (myReader["PassWord"].ToString());
}
myConn.Close();

DataGridView Updating database

When I use the following code the loop is iterating twice and I am getting error message as "The variable name '#projectName1' has already been declared. Variable names must be unique within a query batch or stored procedure." and resetting all the values of the table in the datagridview as well as in the table. Actually I want to update the DataGridView in the form itself by selecting the cell and it should reflect the same in the database too.
private void btnUpdate_Click(object sender, EventArgs e)
{
SqlConnection con = Helper.getconnection();
con.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
string myCmd = string.Empty;
foreach (DataGridViewRow myDgrow in dataGridView2.Rows)
{
myCmd = "Update Details set ProjectName='" + myDgrow.Cells["ProjectName"].Value + "', Description = '" + myDgrow.Cells["Description"].Value + "', DateStarted='" + myDgrow.Cells["DateStarted"].Value + "',TeamSize='" + myDgrow.Cells["TeamSize"].Value + "',Manager='" + myDgrow.Cells["Manager"].Value + "'";
cmd.Parameters.AddWithValue("#projectName1", myDgrow.Cells["ProjectName"].Value);
cmd.Parameters.AddWithValue("#Description1", myDgrow.Cells["Description"].Value);
cmd.Parameters.AddWithValue("#DateStarted1", myDgrow.Cells["DateStarted"].Value);
cmd.Parameters.AddWithValue("#TeamSize1", myDgrow.Cells["TeamSize"].Value);
cmd.Parameters.AddWithValue("#Manager1", myDgrow.Cells["Manager"].Value);
cmd.CommandText = myCmd;
cmd.ExecuteNonQuery();
dataGridView2.Update();
myCmd = string.Empty;
}
DataTable details = new DataTable();
SqlDataAdapter da = new SqlDataAdapter();
try
{
da.Update(details);
}
catch (Exception exceptionObj)
{
MessageBox.Show(exceptionObj.Message.ToString());
}
}
You are using foreach loop and adding the parameters each time to the same command. Either clear the parameters each time you iterate in the loop or create a new command each time..

Trouble with query, execute non scalar not behaving as I thought

I'm having trouble with a SQL query:
using (SqlConnection conn = new SqlConnection("user id=user;" + "password=pass;" + "server=server;" + "database=db;"))
{
using (SqlCommand comm = new SqlCommand(#"SELECT COUNT(*) FROM [CompaniesDB].[dbo].[Companies] WHERE BolagsID = '" + BolagsID + "'"))
{
conn.Open();
comm.Connection = conn;
MessageBox.Show("TEST: {0}", Convert.ToString((int)comm.ExecuteScalar()));
}
}
I'm expecting to get an int in the message box conveying the number of rows that BolagsID occurs in. But I get 0 every time. I've tried the query in SQL Server Management Studio and it works fine there. What am I doing wrong/missing?
EDIT:
This works, but now I don't know how to parameterize the values:
string query = #"SELECT COUNT(*) FROM [CompaniesDB].[dbo].[Companies] WHERE BolagsID = " + BolagsID;
ADODB.Connection conn2 = new ADODB.Connection();
ADODB.Recordset rs = new ADODB.Recordset();
string strConn = "Provider=...;Data Source=...;Database=...;User Id=...;Password=...";
conn2.Open(strConn);
rs.CursorType = ADODB.CursorTypeEnum.adOpenStatic;
rs.Open(query, conn2);
if (rs.Fields[0].Value > 0)
...stuff...
Like others are saying, parameters are a good idea. Here's something to get you started:
string query = #"SELECT Count(*) FROM [CompaniesDB].[dbo].[Companies] WHERE BolagsID = #BolagsID";
using (SqlCommand cmd = new SqlCommand(query, conn))
{
cmd.Parameters.Add("#BolagsID", SqlDbType.NVarChar).Value = BolagsID;
conn.Open();
MessageBox.Show("TEST: {0}", Convert.ToString((int)cmd.ExecuteScalar()));
conn.Close();
}
Basically a 0 is returned if there is an error in your query, so even though SSMS is smart enough to resolve it, the sql command isn't.
A quick way to make sure that everything else is working okay is to change the query to just "SELECT Count(*) FROM [CompaniesDB].[dbo].[Companies]". If that doesn't work then the issue could lie with your database connection (permissions?) or something else.
Try assigning SELECT COUNT(*) FROM [CompaniesDB].[dbo].[Companies] WHERE BolagsID = '" + BolagsID + "'" to a string str as follows
string str =#"SELECT COUNT(*) FROM [CompaniesDB].[dbo].[Companies] WHERE BolagsID = '" + BolagsID + "'";
using (SqlConnection conn = new SqlConnection("user id=user;" + "password=pass;" + "server=server;" + "database=db;"))
{
using (SqlCommand comm = new SqlCommand(str))
{
conn.Open();
comm.Connection = conn;
MessageBox.Show("TEST: {0}", Convert.ToString((int)comm.ExecuteScalar()));
}
}
Then do a watch/quickwatch on str's value to get the exact query that is getting run and then run the same query in Sql Managment studio. If you get 0 in Sql Management Studio as well, then the problem is that the data is just not there.
I tried a lot of stuff before trying out a whole different approach. This gives me the result I want:
string query = #"SELECT COUNT(*) FROM [CompaniesDB].[dbo].[Companies] WHERE BolagsID = " + BolagsID;
ADODB.Connection conn2 = new ADODB.Connection();
ADODB.Recordset rs = new ADODB.Recordset();
string strConn = "Provider=...;Data Source=...;Database=...;User Id=...;Password=...";
conn2.Open(strConn);
rs.CursorType = ADODB.CursorTypeEnum.adOpenStatic;
rs.Open(query, conn2);
if (rs.Fields[0].Value > 0)
...stuff...
Note that both connection and record set are closed outside of this code snippet.

Categories

Resources