The parameterized query expects parameter xy which was not supplied - c#

I'm trying to do an app without adding some details about a car delivery.
I wrote the code in C# and SQL, but when I add the data to textbox, radiobutton, labels, etc. I get this error:
System.Data.SqlClient.SqlException: 'The parameterized query '(#a int,#b nvarchar(7),#c int,#d nvarchar(12),#e nvarchar(10),#f' expects the parameter '#f', which was not supplied.'
But I tried by debug to see if they take values and all have values less #f
The length of the columns in the database is 50 or 100
if (materialRadioButton5.Checked)
{
choose = "Excelent";
}
else if (materialRadioButton8.Checked)
{
choose = "Foarte bună";
}
else if (materialRadioButton7.Checked)
{
choose = "Bună";
}
else if (materialRadioButton6.Checked)
{
choose = "Uzată";
}
if (materialRadioButton4.Checked)
{
chooser = "Mulţumit";
}
else if (materialRadioButton1.Checked)
{
chooser = "Nemulţumit";
}
SqlConnection con = new SqlConnection(stringcon);
SqlCommand cmd = new SqlCommand();
con.Open();
cmd.Connection = con;
cmd.Parameters.Clear();
cmd.CommandText = "insert into returncar(id_client,fullname_client,id_team,fullname_team,rendition,condition,team_mention,customers_plesed,exp_felt,client_mention) values(#a,#b,#c,#d,#e,#f,#g,#h,#i,#j)";
cmd.Parameters.AddWithValue("#a", Convert.ToInt32(label65.Text));
cmd.Parameters.AddWithValue("#b", label67.Text);
cmd.Parameters.AddWithValue("#c", Convert.ToInt32(label66.Text));
cmd.Parameters.AddWithValue("#d", label68.Text);
cmd.Parameters.AddWithValue("#e", metroDateTime1.Text);
cmd.Parameters.AddWithValue("#f", choose);
cmd.Parameters.AddWithValue("#g", firstname_textbox.Text);
cmd.Parameters.AddWithValue("#h", chooser);
cmd.Parameters.AddWithValue("#i", role_dropbox.selectedValue);
cmd.Parameters.AddWithValue("#j", materialSingleLineTextField1.Text);
cmd.ExecuteNonQuery();
SqlCommand cmd2 = new SqlCommand();
cmd2.Connection = con;
cmd2.Parameters.Clear();
cmd2.CommandText = "update rentcar set inchiriat=0 where id=#id";
cmd2.Parameters.AddWithValue("#id", Form2.idddloan);
cmd2.ExecuteNonQuery();
con.Close();
panel2.Visible = false;
bunifuFlatButton7.Visible = false;
How radiobutton4 and radiobutton1 works and the others do not?...
public string choose, chooser;

If the value is null then the parameter is not added and you'll get the exception you mentioned. In these cases make sure to check for null and instead pass
choose ?? Value.DBNull

Related

Parameter #un must be defined

I'm getting this error
"MySql.Data.MySqlClient.MySqlException: 'Fatal error encountered
during command execution.", "MySqlException: Parameter '#un' must be
defined."
and I don't know what to do honestly I'm just following what my friend is doing and I'm just a complete newbie in coding. Here is my code.
private void BTNDELETE_Click(object sender, EventArgs e)
{
var c = cmd.Parameters;
con.ConnectionString = Properties.Settings.Default.sampledb_it11ConnectionString;
con.Open();
cmd.Connection = con;
cmd = new MySqlCommand("delete tbl_user set username=#un, password=#pw, usertype=#ut, loginname=#ln where username=#un,", con);
c.Clear();
c.AddWithValue("#un", TXTUN.Text);
c.AddWithValue("#pw", TXTPW.Text);
c.AddWithValue("#ut", CBOUT.Text);
c.AddWithValue("#ln", TXTLN.Text);
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Record has been deleted", "Deleting Successful", MessageBoxButtons.OK, MessageBoxIcon.Information);
TXTUN.Text = "";
TXTPW.Text = "";
TXTCPW.Text = "";
TXTLN.Text = "";
CBOUT.Text = "";
TXTUN.Focus();
DG_Refresh();
TXTUN.Enabled = true;
}
The error or "MySqlException: Parameter '#un' must be defined." is caused by undefined parameters of the MySqlCommand object. It is incorrect to store the parameters in 'c':
var c = cmd.Parameters;
c.AddWithValue("#un", TXTUN.Text);
I would suggest you revise it to :
cmd.Parameters.AddWithValue("#un", TXTUN.Text);
Additionally, the sql scripts are messed up. From the MessageBox and the name of button, it seems you mean to delete a row in the database. So the script should be:
cmd = new MySqlCommand("delete tbl_user where username=#un,", con);
Looks like what your friend do is to update a row while you are going to delete a row. The keyword 'set' should be paired with 'update' command.
And it is incorrect to create a new instance of MySqlCommand after assigning the connection.
cmd.Connection = con;
cmd = new MySqlCommand...
Finally, the code statements would be like this:
con.ConnectionString = Properties.Settings.Default.sampledb_it11ConnectionString;
con.Open();
MySqlCommand cmd = new MySqlCommand("delete tbl_user where username=#un,", con);
cmd.Connection = con;
cmd.Parameters.AddWithValue("#un", TXTUN.Text);
cmd.ExecuteNonQuery();
con.Close();

I have two sql columns that have integer values, so how can i set to increase for 1 without manually insert data?

I have two sql columns that have integer values, so how can i set to increase for 1 without manually insert data?
public bool changeData(classIP CIobject)
{
bool check = false;
clConnection clConn = new clConnection();
SqlConnection conn = clConn.openConnection();
SqlCommand comm = new SqlCommand();
comm.Connection = conn;
comm.CommandText = "UPDATE userTBL SET SifraPrimac=#SifraPrimac, SifraIsplakac=#SifraIsplakac";
I need to add values for SifraPrimac and SifraIsplakac by increasing for one
comm.Parameters.Add("#SifraPrimac", SqlDbType.Int).Value = CIobject.SifraPrimac;
comm.Parameters.Add("#SifraIsplakac", SqlDbType.Int).Value = CIobject.SifraIsplakac;
if (comm.ExecuteNonQuery() >= 0)
{
check = true;
}
comm.Dispose();
return check;
}
You don't need to get their values add 1 in c# and then set the values again. just let do the adding in your SQL query.
clConnection clConn = new clConnection();
SqlConnection conn = clConn.openConnection();
SqlCommand comm = new SqlCommand();
comm.Connection = conn;
comm.CommandText = "UPDATE userTBL SET SifraPrimac=SifraPrimac+1, SifraIsplakac=SifraIsplakac+1";
comm.ExecuteNonQuery();

C# SQL, Multiple Commands

I'm trying to write a method which should communicate with database, but I'm not sure if my approach is right.
public void dbWorkerLogin(int workerNumber) {
// Connection string stored in "conn"
if (!new SqlCommand("Some Command WHERE id=" +workernumber,conn).executeReader().HasRows)
{
new SqlCommand("exec STORED_PROCEDURE1 " + workerNumber, conn).ExecuteNonQuery();
new SqlCommand("exec STORED_PROCEDURE2 " + workerNumber, conn).ExecuteNonQuery();
}
else
{
new SqlCommand("exec STORED_PROCEDURE3 " + workerNumber,conn).ExecuteNonQuerry();
}
1) Is it ok to write it like this and start each SqlCommand with keyword new? Or should I do something like:
SqlCommand command = new SqlCommand(null, conn);
command = ...;
and then recycle the variable 'command' or this way?
using(SqlCommand cmd = new SqlCommand("COMMAND", conn);
2) Will my procedures work or should I use SqlCommand.Prepare() function that will covert my data into correct datatypes? eg. workerNumber is int, but in database it is stored as decimal.
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parametres.Add("#id", SqlDbType.Decimal).Value = workNumber;
cmd.Prepare();
cmd.ExecuteNonQuery();
}
Can you please somehow sum up what to use, what better not to? Unfortunately I can't test that first code because of limited access to DB so I'm not sure if it can be executed without errors or not.
Thank you for any help on this subject!
EDIT:
After a few hours I reach to this stage:
public int getWorkerNumber(string uniqueID)
{
using (conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnect"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT number FROM worker WHERE workerID = #id",conn))
{
cmd.Parameters.Add("#id", SqlDbType.Decimal).Value = uniqueID;
using (SqlDataReader reader = cmd.ExecuteReader())
{
int answer;
while (reader.Read())
{
answer = (int)reader.GetDecimal(0);
}
return answer;
}
}
}
}
And this one:
public string dbLoginWorker(int workerNumber)
{
SqlCommand cmd;
SqlDataReader reader;
using (conn = new SqlConnection(ConfigurationManager.ConnectionStrings["dbConnect"].ConnectionString))
{
conn.Open();
cmd = new SqlCommand("SELECT column FROM table WHERE id= #workernumber", conn);
cmd.Parameters.Add("#workernumber", SqlDbType.Decimal).Value = workerNumber;
reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
cmd = new SqlCommand("STORED_PROCEDURE1", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal).Value = workerNumber;
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar).Value = "text";
cmd.Prepare();
reader.Close();
cmd.ExecuteNonQuery();
cmd.Dispose();
reader.Dispose();
return "procedure 1 executed";
else
{
cmd = new SqlCommand("STORED_PROCEDURE2", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal).Value = workerNumber;
cmd.Parameters.Add("#INT", SqlDbType.SmallInt).Value = 1;
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar).Value = "text";
cmd.Prepare();
reader.Close();
cmd.ExecuteNonQuery();
cmd.Dispose();
reader.Dispose();
return "procedure 2 executed";
}
}
}
Both methods are functional (if I did no mistake in rewriting :) ). I'm not sure which of these methods (1st or 2nd) are better in terms of stability and if this approach is better and more ressistant to SQL Injection. Can someone comment on this subject? Thank you again for any help!
1) It is best to always use USING blocks when possible. This includes SqlConnection, SqlCommand, SqlReader and other objects that implement IDisposable. USING blocks automatically close and dispose of the objects, so you do not have to do so.
2) I believe that you are using the Prepare() method in the wrong place. Look at the following StackOverflow article for proper usage:
PrepareMethodInstructions.
3) in the dbLoginWorker() method, the first query is just used to determine if rows are found. Therefore, I suggest changing the SELECT command to SELECT TOP 1 column FROM table WHERE id= #workernumber so that the query is faster and more efficient.
4) I do not believe your commands are subject to SQL Injection attacks because they are fully parameterized. Good job on that one.
5) As a general thought, I suggest reading up on refactoring techniques. Your dbLoginWorker() method could be made more readable and maintainable, as well as self-documenting, if you created three additional methods, one for each SQL command, and named them something appropriate. You could also setup a method for creating a connection based on a connection name, and you would not have as much duplicate code. For example:
public static SqlConnection GetConnection(string connectionName)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings[connectionName].ConnectionString);
conn.Open();
return conn;
}
public string dbLoginWorker(int workerNumber)
{
using (conn = GetConnection("dbConnect"))
{
if (CanFindWorkerNumber(conn, workerNumber))
ExecuteProcedure1(conn);
else
ExecuteProcedure2(conn);
}
}
public bool CanFindWorkerNumber (SqlConnection conn, int workerNumber)
{
bool success = false;
using (SqlCommand cmd = new SqlCommand("SELECT TOP 1 column FROM table WHERE id= #workernumber", conn))
{
cmd.Parameters.Add("#workernumber", SqlDbType.Decimal);
cmd.Prepare();
cmd.Parameters[0].Value = workerNumber;
success = cmd.ExecuteScalar() != null;
}
return success;
}
public void ExecuteProcedure1(SqlConnection conn)
{
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE1", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal);
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar);
cmd.Prepare();
cmd.Parameters[0].Value = workerNumber;
cmd.Parameters[1].Value = "text";
cmd.ExecuteNonQuery();
}
}
public void ExecuteProcedure1(SqlConnection conn)
{
using (SqlCommand cmd = new SqlCommand("STORED_PROCEDURE1", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#ID", SqlDbType.Decimal);
cmd.Parameters.Add("#INT", SqlDbType.SmallInt).Value);
cmd.Parameters.Add("#VARCHAR", SqlDbType.VarChar);
cmd.Prepare();
cmd.Parameters[0] = workerNumber;
cmd.Parameters[1] = 1;
cmd.Parameters[2] = "text";
cmd.ExecuteNonQuery();
}
}
You could actually do this in one SQL commend. Right now you are pulling back a result set only to see if it has rows or not, then executing different commands based on that. You should be able to do that in one command, disposing of it and the connection appropriately:
var sql =
#"
IF EXISTS(Some Command WHERE id=#workernumber)
BEGIN
exec STORED_PROCEDURE1 #workernumber;
exec STORED_PROCEDURE2 #workernumber;
END
ELSE
exec STORED_PROCEDURE3 #workernumber;
";
Note that you're not vulnerable to SQL injection because you're not dealing with strings, only integers.

Showing MessageBox when value is lower than -

Basically I want a MessageBox that appears when my Form is loaded that is saying that the value is lower than a constant value ( like 30 ).
This is the code I just wrote but its not working since the IF condition is not syntactly correct.
private void button2_Click(object sender, EventArgs e)
{
System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection();
conn.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=|DataDirectory|DataMG.mdb";
System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = "Select COUNT(*) from Prodotti where Disponibilta < 30";
cmd.Connection = conn;
conn.Open();
var count = (int)cmd.ExecuteScalar();
if (count < 0)
{
MessageBox.Show("Attenzione alcuni prodotti sono in disponibilita' limitata!");
conn.Close();
}
}
What should I do ?
Thanks
Try something like this:
using (var cmd = new OleDbCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select COUNT(*) from Prodotti where Disponibilta < 30";
var count = (int)cmd.ExecuteScalar();
if (count > 0)
{
MessageBox.Show("Attenzione alcuni prodotti sono in disponibilita' limitata!");
//connection.Close(); wrap connection around an using
}
}
Basically you ask to database the number of Prodotti that Disponibilta < 30, so if any you show the messagebox.
EDIT
I assume that Disponibilta is a numeric.
You shouldn't use ExecuteNonQuery() with a simple SELECT statement, SQLDataReader is quicker and the proper way to do this:
cmd.CommandText = "SELECT * FROM Prodotti WHERE Disponibilta < 30";
conn.Open();
MySqlDataReader myReader = cmd.ExecuteReader();
if(myReader.HasRows)
{
//This means you have at least one product with less than 30.
}
myReader.Close();
conn.Close();
Select keyword introduces a query, so you have to use .ExecuteReader()..ExecuteNonQuery() is used for INSERT, DELETE, UPDATE and return value is the number of rows affected.
For your situation, create a reader and check the first value
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read()
{
if (reader[0] < aValue) //make here the appropiate conversion
{
MessageBox.Show("Attenzione alcuni prodotti sono in disponibilita' limitata!");
connection.Close();
break;//maybe return?
}
}

Procedure or function sp_Record has too many arguments specified

This is the code I'm using to insert records into SQL SERVER DB
while (dr.Read())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_InsertEmailRecord";
cmd.Connection = con;
cmd.Parameters.AddWithValue("#mId", memberId);
cmd.Parameters.AddWithValue("#companyName", dr.GetValue(0));
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
First Record insert successfully, but when it runs for second it return error
Procedure or function sp_Record has too many arguments specified
parameters added up
mean in first insert parameters = 2 & in next it added 2 more....
how to resolve???
Because your SqlCommand has already defined #mId and #companyName parameter since you didn't clear your parameters.
You have 2 options;
Use cmd.Parameters.Clear() to clear your parameter at the end of your while statement.
Or create a new SqlCommand object top of your while statement like SqlCommand cmd = new SqlCommand()
Looks like most correct way is to define your #companyName parameter name before your while and add it's value in while statement like John Saunders mentioned.
Also use using statement to dispose your SqlDataReader like;
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr != null)
{
while (dr.Read())
{
//do something
}
}
}
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "sp_InsertEmailRecord";
cmd.Connection = con;
cmd.Parameters.AddWithValue("#mId", memberId);
cmd.Parameters.Add("#companyName");
con.Open();
while (dr.Read())
{
cmd.Parameters["#companyName"].Value = dr.GetValue(0);
cmd.ExecuteNonQuery();
}
con.Close();

Categories