I'm very new in C#. I've written a small code. Can you help me with it :
Here is my code :
private void button1_Click(object sender, EventArgs e)
{
string povezava = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\Users\\Matic\\Documents\\FERI\\2.LETNIK\\1.SEMESTER\\RPS\\VAJA3\\bazaPodatkov.accdb";
string zapisi = "update Zaposleni set ID='" + this.textBox1.Text +
"',Ime='" + this.textBox2.Text +
"',Priimek='" + this.textBox3.Text +
"',Uporabnisko_ime='" + this.textBox4.Text +
"',Geslo='" + this.textBox5.Text +
"',E_posta='" + this.textBox6.Text +
"',Ulica='" + this.textBox7.Text +
"',Hisna_stevilka='" + this.textBox8.Text +
"',Mesto='" + this.textBox9.Text +
"',Delovno_mesto='" + this.textBox10.Text +
"' where ID='" + this.textBox1.Text + "';";
OleDbConnection baza = new OleDbConnection(povezava);
OleDbCommand beri = new OleDbCommand(zapisi, baza);
OleDbDataReader branje;
try
{
baza.Open();
branje = beri.ExecuteReader();
MessageBox.Show("Podatki so shranjeni.");
while (branje.Read())
{
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I'm having a datatype mismatch in criteria expression.
Do you see anything wrong in my code ?
You code contains some visible errors and probably some invisible errors.
First problem.
Never do a string concatenation to build sql queries. Use always a parameterized query.
You put placeholders (? for OleDb/Access) where you want to put the values and then build a collection of parameters where you set the values. It is the framework code that substitutes the placeholders with the parameter's values putting the appropriate quotes around the values and removing the possibility of sql injection attacks (Little Bobby Tables).
Second, you have an update query, then there is no sense in returning an OleDbDataReader.
Just execute the command (by calling ExecuteNonQuery) and eventually check if the query updates any rows.
Third, enclose the OleDbConnection/Command with the using statement to ensure proper closing and cleanup of the connection and the command.
private void button1_Click(object sender, EventArgs e)
{
string povezava = "........."
string zapisi = "update Zaposleni set ID=?,Ime=?,Priimek=?,Uporabnisko_ime=?,Geslo=?," +
"E_posta=?,Ulica=?,Hisna_stevilka=?,Mesto=?,Delovno_mesto=? " +
"where ID=?";
try
{
using(OleDbConnection baza = new OleDbConnection(povezava))
using(OleDbCommand beri = new OleDbCommand(zapisi, baza))
{
baza.Open();
beri.Parameters.AddWithValue("#p1",this.textBox1.Text);
beri.Parameters.AddWithValue("#p2",this.textBox2.Text);
beri.Parameters.AddWithValue("#p3",this.textBox3.Text);
.... and so on for the other parameters
beri.Parameters.AddWithValue("#p11",this.textBox1.Text);
int rowsAffected = beri.ExecuteNonQuery();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Finally, the invisible errors. You pass all of your values as strings. This is correct only if the database fields that receive the values are text fields. If one or more of your fields is not a string, (for example a date or an integer) then trying to set its value to a string triggers the datatype mismatch in criteria expression error message.
If this is the case then you need to convert the string to the appropriate datatype.
For example (assuming that the ID field is a numeric field)
beri.Parameters.AddWithValue("#p1",Convert.ToInt32(this.textBox1.Text));
You have one extra semicolon end of your command string (zapisi) delete it and try again.
Also consider using parameterized queries
Related
the code is below and the error starting from sqlCommand cmd the 13th line of this code
private void button2_Click(object sender, EventArgs e)
{
if (StudenUsn.Text == "" )
{
MessageBox.Show("Enter The Student Number");
} else {
Con.Open();
String query = "update Student_tbl set StdName='" + StudName.Text + "',where FatherName='" + FtName.Text + "',where MotherName='" + MtName.Text + "',where StdAddress='" + Address.Text + "',where Collage ='" + Collage.Text + "'set StdRoom = " + StRmNum.SelectedValue.ToString()+",StdStatus = '"+ StudSt.SelectedItem.ToString() + "' where StdUsn ='"+StudenUsn+ "')";
SqlCommand cmd = new SqlCommand(query, Con);
cmd.ExecuteNonQuery();
MessageBox.Show("Room Successfully Updates");
Con.Close();
FillStudentDGV();
}
}
Your code should look more like:
private void button2_Click(object sender, EventArgs e)
{
if (StudenUsn.Text == "" )
{
MessageBox.Show("Enter The Student Number");
} else {
var query = #"
update Student_tbl
set
StdName=#sn,
FatherName=#fn,
MotherName=#mn,
StdAddress=#sa,
Collage=#c,
StdRoom=#sr,
StdStatus=#ss
where
StdUsn=#su";
using var con = new SqlConnection(YOUR_CONN_STR_HERE);
using var cmd = new SqlCommand(query, con);
cmd.Parameters.AddWithValue(#sn, StudName.Text);
cmd.Parameters.AddWithValue(#fn, FtName.Text);
cmd.Parameters.AddWithValue(#mn, MtName.Text);
cmd.Parameters.AddWithValue(#sa, Address.Text);
cmd.Parameters.AddWithValue(#c, Collage.Text);
cmd.Parameters.AddWithValue(#sr, StRmNum.SelectedValue);
cmd.Parameters.AddWithValue(#ss, StudSt.SelectedItem);
cmd.Parameters.AddWithValue(#su, StudenUsn);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Room Successfully Updates");
FillStudentDGV();
}
}
There are good reasons to avoid using AddWithValue if you use SQLServer which you can get into at a later date if you want, but it's convenient for me (who doesn't know the types and widths of your columns) dealing with the current massive elephant in the room which is your SQL is massively vulnerable to a hacking technique known as sql injection (and to a lesser extent it would blow up with an error for any student whose name included an apostrophe) - using AddWithValue might make your query slightly slower, but better that than it be the cause of the next data breach; learn how to write SQLs right, right now
Never ever take data supplied by a user and concatenate it into an SQL string. Doing so essentially, in most cases, gives the user access to your database. So many big companies whose developers should know better, put up expensive firewalls and security and then let anyone in via this back door anyway; sql injection prone systems are one of the leading causes of hacks in the world today
Always use #parameter placeholders in the SQL for user data and add a parameter to the command's parameters collection, containing the data
Now on the topic of your actual error; the pattern for an update is
update table
set col1=#param1, col2=#param2 ...
where (some conditions)
You have one where and one set. If there is some conditional aspect to your set, like you only want to update the student name/address if it is currently null then you can do like:
update table
set
name=case when name is null then #n else name end,
address=case when address is null then #a else address end
where (some conditions)
Or more simply
update table
set
name=coalesce(name, #n)
address=coalesce(address, #a)
where (some conditions)
You can't mix n match and say "where this=that where this2=that2 set this3=that3" - that's a syntax error. Where is for picking the row you want to update and set is for starting a block of commas separated columns and values the row data is to be updated to.
Strive to write your sql nicely formatted inside an #string; it's a programming language all of its own, and will be easier to debug if it's laid out nicely
Can u try with it ?
String query = "update Student_tbl set StdName='" + StudName.Text + "',StdRoom = '" + StRmNum.SelectedValue.ToString()+"',StdStatus = '"+ StudSt.SelectedItem.ToString() + "' where FatherName='" + FtName.Text + "' and MotherName='" + MtName.Text + "' and StdAddress='" + Address.Text + "' and Collage ='" + Collage.Text + "' and StdUsn ='"+StudenUsn+ "'";
I am making DatabaseManager class for my solution and I am getting the number 0 when I am trying to update the text.
For example : I have now the name michael and I wanted to change it to "michael , mike" so I'll probably use update.
public void AddCrime(CSteamID id, string crime, string time)
{
try
{
MySqlConnection connection = createConnection();
MySqlCommand command = connection.CreateCommand();
crime = "," + crime;
command.CommandText = "update `" + Main.Instance.Configuration.Instance.DatabaseTableName
+ "` set `crime` = crime + ( #crime ) where `steamId` = #steamID; select `crime` from `"
+ Main.Instance.Configuration.Instance.DatabaseTableName
+ "` where `steamId` = #steamID";
command.Parameters.AddWithValue("#steamID", id);
command.Parameters.AddWithValue("#crime", crime);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
AddTime(id, time);
}
catch (Exception ex) { Logger.Log(ex); }
}
How do I call it :
DatabaseManager.AddWanted(player.CSteamID, command[1], command[2]);
Thanks everyone!
yor last sentence in your command is a select statement, NonQuery does not return values, only the number of rows affected. Change it to ExecuteScalar and store the value of the select in a variable.
Second error is the data type of the parameter #steamID. You set the value id, which is declares as CSteamID id... CStreamId is not string, change the AddWithValue
Fixed, I added another method to get crime from table and then changed the void crime string to the current string + the table text.
The error was : Truncated incorrect DOUBLE value.
I'm trying to add a record to a table with data used from a form. My code looks like this:
private void button4_Click(object sender, EventArgs e)
{
using (SqlConnection connect = new SqlConnection(#"Data Source=(LocalDB)\v11.0;" +
#"AttachDbFilename=C:\Development\C-Sharp\LockItUp\Lockitup.mdf;Integrated Security=True"))
{
string theVault = #lblVault.Text.Replace(#"\", #"\\");
string stmt = #"INSERT INTO Users (username,password,folderloc,fullname,email,cellphone)" +
" VALUES ('" + txtUsrName.Text + "', '" + txtUserPassword.Text + "', '" + theVault + "', '" +
txtFullname.Text + "', '" + txtEmail.Text + "', '" + txtCellPhone.Text + "')";
using(SqlCommand cmd = new SqlCommand(stmt, connect))
{
try
{
connect.Open();
cmd.ExecuteNonQuery();
connect.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex);
return;
}
}
PanelSwitch("Home");
RefreshMenu();
}
}
However, every time run it, I get the error message 'String or binary data would be truncated.' I pin pointed the error to the folderloc field. A directory goes in it. I'm currently trying to put the value C:\Development\locker in it, but I keep getting the error. How can I resolve this problem?
You've got several issues with your code. First, to address the error you are receiving String or binary data would be truncated. The reason for this is that the field in the table isn't big enough to store the data. Go into your database and look at the Users table and look at each field and make sure the field is defined with enough width to store the data (e.g., look for VARCHAR(20) or something and change it to something like VARCHAR(500)).
Secondly, as #David suggested, you need to address your issue of SQL Injection. You are directly inserting dynamic values into your SQL statement. This is bad news. Microsoft has a good article on this subject and how to avoid it.
Thirdly, you should not store your passwords as plain text. They should be salted and hashed. Look at this article for a good tutorial on this.
I would like a help please. When I want insert datetimepicker value into my table but he doesn't can insert and he show me a message
Conversion failed when converting date and/or time from character
string
You can help me please !
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void add_Click(object sender, EventArgs e)
{
cmd.CommandText = "Insert into clients values (" + cintxt.Text + ", '" + nomtxt.Text + "', '" + prntxt.Text + "', '" + datenaiss.Value + "', '" + addtxt.Text + "', '" + teltxt.Text + "')";
cnx.Open();
cmd.ExecuteNonQuery();
cnx.Close();
}
Your code that tries to insert the record should be changed to use a parameterized approach.
This could be an example
private void add_Click(object sender, EventArgs e)
{
string commandText = #"Insert into clients values
(#id, #name, #prn, #datan, #addr, #tel)";
using(SqlConnection cnx = new SqlConnection(connectionString))
using(SqlCommand cmd = new SqlCommand(commandText, cnx)
{
cmd.Parameters.AddWithValue("#id", Convert.ToInt32(cintxt.Text));
cmd.Parameters.AddWithValue("#name", nomtxt.Text);
cmd.Parameters.AddWithValue("#prn", prntxt.Text);
cmd.Parameters.AddWithValue("#datan", datenaiss.Value);
cmd.Parameters.AddWithValue("#addr", addtxt.Text);
cmd.Parameters.AddWithValue("#tel", teltxt.Text );
cnx.Open();
cmd.ExecuteNonQuery();
}
}
In this code I have changed something. First, the connection and the command are no more global variables but just local and are enclosed in a using statement that ensure a proper closing and disposing also if, for any reason, the code throws an exception.
Second the command text is no more a concatenation of strings, but it is only a single string with parameters placeholders. Concatenating string to build command texts is really a bad practice. Sql Injection hackers wait for commands built in this way to hit your database and, as you have already seen, more often than not, the underlying datatable doesn't understand a string that represent a date to be a valid date.
Finally the command parameters collection is filled with a parameter for every field expected by the command text placeholders. Notice that in this way you build parameters that are of the datatype of the value passed not simply strings that are not expected by the datatable fields. Of course in your actual situation it is possible that some of these parameters should be changed to match exactly your datatable field (for example I don't know id the first field is an integer or not)
EDIT As requested by comments below I add also some considerations on the method AddWithValue.
While it is convenient and expressive it could be a problem if your program call this code with frequency or if your database is under heavy use. The preferred method to use is
cmd.Parameters.Add("#name", SqlDbType.NVarChar, 50).Value = nomtxt.Text;
.....
See MSDN SqlParameterCollection.Add
and more info about the difference between Add and AddWithValue are explained here
How Data Access Code Affects Database Performance
I've been working on a delete function for a while now, and I cannot get past this error.
Delete Failed ORA-00904 "SYSTEM"."DATA"."DATAROWVIEW": invalid identifier
private void button3_Click(object sender, EventArgs e)
{
string yesNoPrompt = "Are you sure you want to delete this patient?";
const string caption = "";
var result = MessageBox.Show(yesNoPrompt, caption,
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
string sql = "DELETE FROM CLIENT WHERE (CLI_LNAME =" + listBox1.SelectedItem.ToString() + ")" ;
try
{
string connectionString = GetConnectionString();
using (OracleConnection connection = new OracleConnection())
{
connection.ConnectionString = connectionString;
connection.Open();
OracleCommand command = new OracleCommand(sql, connection);
command.CommandType = CommandType.Text;
command.ExecuteNonQuery();
}
}
catch (System.Data.OracleClient.OracleException ex)
{
MessageBox.Show("Delete Failed" + ex.Message);
}
}
}
The table in the database is CLIENT and I am trying to find a specific person by their last name, or CLI_LNAME. I don't think the problem is in the name being passed, but more of how it is being passed.
Any ideas?
Your query gets translated to
DELETE FROM CLIENT WHERE (CLI_LNAME = SYSTEM.DATA.DATAROWVIEW)
Due to the missing single quotes and hence its trying to find a column named SYSTEM.DATA.DATAROWVIEW which is not present in the Client table. hence the error.
When you use single quotes then its looking for the text in that particular column
DELETE FROM CLIENT WHERE (CLI_LNAME = 'PatientName') // Now its not a column as such
Use Parameterized queries to avoid SQL injection
Looks like listBox1.SelectedItem.ToString() returns "SYSTEM"."DATA"."DATAROWVIEW". You probably want to access a specific item of the DataRowView that's the SelectedItem, not the entire DataRowView object itself. Maybe listBox1.SelectedItem[0].ToString() is what you want?.
Also you have to add quotes as #Habib.OSU mentions.
And the obligatory sql injection warning: Don't concatenate user inputs into SQL string. It opens up for SQL injection attacks. Use parameterized queries.
you are missing single quote in parameters
string sql = "DELETE FROM CLIENT WHERE (CLI_LNAME ='" + listBox1.SelectedItem.ToString() + "')" ;
Its better if you could use Parameterized query