Database values in textbox if select Combobox - c#

I am trying to write code for a form that writes to a sql table. I use data form other tables to complete the form (along with user input). I have a checkbox that options the source of a combobox (ddDefect) - it is based on one of two sql LIKE queries - so, the combox will display the results of one LIKE query if the checkbox = true and the other LIKE query if it = false. This part works great. Problem is; I cannot seem to figure out how to take the selected item in the combobox and display text form another column in my textbox (txtNcm)
I have tried various ways and this seems to make the most sense to me (though I am only a beginner and clueless) but I get nothing in my text box.
here is the code that I have been trying:
private void ddDefect_SelectedIndexChanged(object sender, EventArgs e)
{
string constring = "Data Source=TS-ERP01;Initial Catalog=Touchstn02;Integrated Security=True";
string Query = "select * from Defect_Codes Where DESCP_91= ' " + ddDefect.Text + " ';";
SqlConnection conDataBase = new SqlConnection(constring);
SqlCommand cmdDataBase = new SqlCommand(Query, conDataBase);
SqlDataReader myReader;
try
{
conDataBase.Open();
myReader = cmdDataBase.ExecuteReader();
while (myReader.Read())
{
string sDEF = myReader["DEFECT_91"] as String;
txtNcm.Text = sDEF;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

Your sql command text contains spaces before and after the value of ddDefect.
....DESCP_91= ' " + ddDefect.Text + " ';";
^ ^
These spaces will be passed as is to the database engine and, unless you have a very specific datatype in the database column (CHAR/NCHAR) with these exact spaces around the values in the column, the command will never find any data.
But this is not the end of your problems. Concatenating strings in this way is a well known source of problems. What if the ddDefect.Text contains a single quote? Another syntax error. Then there is the problem of Sql Injection vulnerability, a very serious security problem.
So you should use a parameterized query like this
string constring = "Data Source=TS-ERP01;Initial Catalog=Touchstn02;Integrated Security=True";
string Query = "select * from Defect_Codes Where DESCP_91= #ds91";
using(SqlConnection conDataBase = new SqlConnection(constring))
using(SqlCommand cmdDataBase = new SqlCommand(Query, conDataBase))
{
try
{
conDataBase.Open();
cmdDataBase.Parameters.Add("#ds91", SqlDbType.NVarChar).Value = ddDefect.Text;
using(SqlDataReader myReader = cmdDataBase.ExecuteReader())
{
while (myReader.Read())
{
string sDEF = myReader["DEFECT_91"].ToString();
txtNcm.Text = sDEF;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Notice also that SqlConnection, SqlCommand and SqlDataReader are disposable objects and thus you should try to always use the using statement to be certain that these objects free the unmanaged resources acquired during they work (particularly the SqlConnection object)

Related

SQL Invalid Column name detection from Query

I've tried running the code and I have no idea what's wrong with the query. Because it keeps saying invalid column name, when I'm trying to retrieve the data from that column instead. The column name matches the one in the DB. It's well connected because it's connected to a login form where it detects the other given password and name. I'm using based on a search textbox.
private void btnSearch_Click(object sender, EventArgs e)
{
SqlConnection cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDetailConnectionString"].ToString());
try
{
cnn.Open();
SqlCommand command = new SqlCommand();
command.Connection = cnn;
string query = "SELECT *FROM AffiliatedRegister WHERE Username=" + txtUser.Text + "";
command.CommandText = query;
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
---[Converting String from db /Insert to textboxes]---
}
cnn.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error" + ex);
}
}
You need to wrap the username text in quotes.
Your emitted sql script is gonna look like:
SELECT *FROM AffiliatedRegister WHERE Username=InputUserName
So SQL is trying to compare the column Username to the column InputUsername.
Once you wrap the user name in quotes, it would be:
SELECT *FROM AffiliatedRegister WHERE Username='InputUserName'
Your statement erred because you did not wrap your string in quotes so Sql interpeted it as on object and not a string. That being said there you should use parameters and not string concatenation.
Use parameters
Wrap your SqlConnection in a using block
You should specify the column order in the SELECT statement, do not use *.
Do not swallow an Exception unless you know how to recover from it
Update code
private void btnSearch_Click(object sender, EventArgs e)
{
// use ConnectionString property
// wrap in using block
using (SqlConnection cnn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyDetailConnectionString"].ConnectionString))
{
try
{
SqlCommand command = new SqlCommand();
command.Connection = cnn;
// use parameters
// avoid *, specify columns instead
string query = "SELECT * FROM AffiliatedRegister WHERE Username= #userName";
command.CommandText = query;
// use parameters, I assumed the parameter type and length - it should be updated to the type and length specified in your table schema
command.Parameters.Add(new SqlParameter("#userName", SqlDbType.VarChar, 200) {Value = txtUser.Text });
// open as late as possible
cnn.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
// ---[Converting String from db / Insert to textboxes]-- -
}
}
catch (Exception ex)
{
MessageBox.Show("Error" + ex);
// do not swallow the exception unless you know how to recover from it
throw;
}
}
}
Well first of all your query is very dangerous so please don't use it for production purpose.
Now what you need to do :-
In your query you need single quotes around the txtUser.Text.
Like this :-
"SELECT *FROM AffiliatedRegister WHERE Username='" + txtUser.Text
+ "'";
Resulting query : SELECT *FROM AffiliatedRegister WHERE Username = 'txtUser.Text';
You can also put double quotes like :-
...Username=\"" + txtUser.Text + "\"";
its complicated ;-) Earlier one is better for the reading purpose.
Why it did not run?
Because all values except integers must be passed inside single or double quotes in a query. Like :-
SELECT * FROM TABLE_NAME WHERE TABLE_NAME.COLUMN_NAME = "VALUE";
Now one very important thing please don't use these kinds of queries for production purpose. I guess you are in development phase so answering this question is not gonna ruin your life ...!!!
You can try to replace the your string: string query = "SELECT *FROM AffiliatedRegister WHERE Username=" + txtUser.Text + "";
to: string query = "SELECT <yourcolumn> FROM AffiliatedRegister WHERE Username=" + txtUser.Text + "";
I believe it is necessary to specify the column name.
Best regards

Print My Search Results From SQL Server on label

I'm just trying to print the sum of my search on a label in form.
Story is I have 2 textboxes that will give me 2 date and searching in my database, and printing the answer of sum cost between that 2 date.
My code is :
private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Data Source=localhost;Initial Catalog=SuperCalc;Integrated Security=True");
SqlCommand com = new SqlCommand();
if (con.State == ConnectionState.Closed)
{
con.Open();
com = new SqlCommand("select sum (Cost) as JameKol From TBL_Cost Where CostDate between '" + textBox1.Text + "' and '" + textBox2.Text + "' ", con);
label5.Text = com();
con.Close();
MessageBox.Show("Search is done", "Done");
}
}
com can't use as a method, so, how can I do this?
Just use ExecuteScalar which is exactly what this for. It gets first column of the first row which fits SUM function.
label5.Text = com.ExecuteScalar().ToString();
But more important, you should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
And use using statement to dispose your connection and command automatically instead of calling Close method manually.
By the way, looks like your CostDate column is character typed. Don't do it. This is a bad habit to kick. You should never keep your DateTime values as a character. Change it to datetime or better datetime2 type and pass your DateTime values directly to your parameterized query. That's why I used DateTime.Parse to parse your Text values. If it can't parse them, you can use ParseExact as well.
string conString = "Data Source=localhost;Initial Catalog=SuperCalc;Integrated Security=True";
using(var con = new SqlConnection(conString))
using(var com = con.CreateCommand())
{
com.CommandText = #"select sum (Cost) as JameKol From TBL_Cost
Where CostDate between #date1 and #date2";
com.Parameters.Add("#date1", SqlDbType.DateTime2).Value = DateTime.Parse(textBox1.Text);
com.Parameters.Add("#date2", SqlDbType.DateTime2).Value = DateTime.Parse(textBox2.Text);
con.Open();
label5.Text = com.ExecuteScalar().ToString();
}

Can't retrieve data from SqlDataReader in C#

I need to insert values into several tables first I have to retrieve university id from table college and then insert faculty name into table faculty and get generated by SQL Server ID. After all of this I have to insert both ids into an other table.
Problem is that I have to close readers and after I do it I can't retrieve those ids from them so variable where they should be saved is null. Here is my code. How to do it correctly?
Sorry I am new to C# and SQL Server.
// reading data into combobox
try
{
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select * from colege", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
comboBox1.Items.Add(myReader["name"].ToString());
// Console.WriteLine(myReader["Column2"].ToString());
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
myConnection.Close();
private void button1_Click(object sender, EventArgs e)
{
string item = comboBox1.Text.ToString();
// MessageBox.Show(item);
SqlConnection myConnection = new SqlConnection("user id=bogdan_db;" +
"password=1234;server=localhost;" +
"Trusted_Connection=yes;" +
"database=cafedrascience; " +
"connection timeout=30");
try
{
myConnection.Open();
}
catch (Exception E)
{
Console.WriteLine(E.ToString());
}
// reading data into combobox
String colegeid = null;
try
{
SqlDataReader myReader = null;
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
colegeid = myReader["id"].ToString();
// Console.WriteLine(myReader["Column2"].ToString());
}
myReader.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
String facultyid = null;
try
{
SqlDataReader myReader1 = null;
SqlCommand myCommand = new SqlCommand("select * from depart where name like'" + textBox1.Text + "'",
myConnection);
myReader1 = myCommand.ExecuteReader();
while (myReader1.Read())
{
facultyid = myReader1["id"].ToString();
}
myReader1.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
SqlCommand myCommand1 = new SqlCommand("INSERT INTO coledge_faculty (coledge_id, faculty_id) " +
"Values ('"+colegeid+"''"+facultyid+"')", myConnection);
myCommand1.ExecuteNonQuery();
// MessageBox.Show(colegeid);
// MessageBox.Show(facultyid);
myConnection.Close();
}
The number one thing I can stress about your code is that you should be using parameterised queries, beyond the obvious risks of SQL Injection, it also protects you against malformed SQL, data truncation through conversion, and it allows you to use cached execution plans.
The next thing to point out is that you should not be using SELECT * in production code, e.g.
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
colegeid = myReader["id"].ToString();
// Console.WriteLine(myReader["Column2"].ToString());
}
Why bother retrieving all the columns of colege from the database, then sending them all over the network if you only care about the column id?
Finally your diagnosis of the problem is not correct:
Problem is that I have to close readers and after I do it, I can't retrieve those ids from them, so variable where they should be saved is null
If you assign the string variable colegeid a value you have retrieved from a data reader, it will not be null after you have closed the reader, it will retain the value you assigned. The most likely reason the variable is null is because your reader returns no rows so you never assign it a value.
Now, rant over, I will actually answer your question. You are massively over complicating the issue, you do not need to retrieve the values into your application tier only to insert them to another table, you can do this all in a single query in your database:
INSERT INTO coledge_faculty (coledge_id, faculty_id)
SELECT c.id, d.id
FROM depart AS d
CROSS JOIN colege AS c
WHERE d.Name = #Depart
AND c.Name = #Colege;
Then it would just be a case of calling this SQL from C#:
string item = comboBox1.Text.ToString();
string connectionString = "user id=bogdan_db; password=1234;server=localhost; Trusted_Connection=yes; database=cafedrascience; connection timeout=30";
string sql = #"INSERT INTO coledge_faculty (coledge_id, faculty_id)
SELECT c.id, d.id
FROM depart AS d
CROSS JOIN colege AS c
WHERE d.Name = #Depart
AND c.Name = #Colege;";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#Colege", SqlDbType.VarChar, 50).Value = item;
command.Parameters.Add("#Depart", SqlDbType.VarChar, 50).Value = textBox1.Text;
connection.Open();
command.ExecuteNonQuery();
}
It is usually a good idea to use using blocks with objects that implement IDisposable, this will ensure the resources are freed up when you are done with them (Don't confuse this with not being able to reuse the connection, .NET has connection pooling in the background so it will reuse connections for you, you shouldn't keep your SqlConnection object open available in case you need to use it again).
On another unrelated note, I also think you are too liberal with try/catch blocks, or at least not dealing with the exception properly, using this one as an example:
try
{
myConnection.Open();
}
catch (Exception E)
{
Console.WriteLine(E.ToString());
}
If myConnection.Open() does throw an error, you still carry on with the method. You will carry on until you get to here:
SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);
myReader = myCommand.ExecuteReader();
Where you will get another exception, something along the lines of the command requiring an open and available SqlConnection, so you go to the exception.
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Again you don't exit the method, but carry on, and you will get the same error later when you try and use the connection again. Again the method carries on and you will use the closed connection a third time to try and insert two variables that were never assigned because exceptions were thrown into your database. Fine, use try catch blocks, but do something meaningful with the exception and exit the method.
private void BtnAdd_Click(object sender, EventArgs e)
{
//con.Open();
cmd = new SqlCommand("INSERT INTO TBL_STORE VALUES (N'"+txt_store_name.Text.Trim()+"',N'"+txt_store_adress.Text.Trim()+"',N'"+txt_store_mobile_1.Text.Trim()+"',N'"+txt_store_mobile_2.Text.Trim()+"',N'"+txt_store_Manger.Text.Trim()+"',N'"+txt_store_Details.Text.Trim()+"')");
cmd.Connection = con;
cmd.ExecuteNonQuery();
cmd.Parameters.AddWithValue("#store_name", txt_store_name.Text.Trim());
cmd.Parameters.AddWithValue("#store_adress", txt_store_adress.Text.Trim());
cmd.Parameters.AddWithValue("#store_mobile_1", txt_store_mobile_1.Text.Trim());
cmd.Parameters.AddWithValue("#store_mobile_2", txt_store_mobile_2.Text.Trim());
cmd.Parameters.AddWithValue("#store_manger", txt_store_Manger.Text.Trim());
cmd.Parameters.AddWithValue("#store_details", txt_store_Details.Text.Trim());
cmd.Parameters.AddWithValue("#Id_store", txt_store_number.Text.Trim());
con.Close();
lbl_store.Text="insert is sucess";
//cmd.Parameters.Add("#store_name", SqlDbType.NVarChar, 50).Value = txt_store_name.Text.Trim();
}

getting exception in creating a password change form

i am creating password change form. when i execute the form and fill the textboxes it give an exception with the message There is already and open DataReader associated with this command which must be closed first.
he is the code which i am using:
private bool CompareStrings(string string1, string string2)
{
return String.Compare(string1, string2, true, System.Globalization.CultureInfo.InvariantCulture) == 0 ? true : false;
}
private void button1_Click(object sender, EventArgs e)
{
try
{
SqlConnection con1 = new SqlConnection();
con1.ConnectionString = "data source=.;Initial catalog=inventory;Integrated Security=true";
con1.Open();
SqlCommand cmd = new SqlCommand("SELECT ISNULL(username, '') AS username, ISNULL(password,'') AS password FROM login WHERE username='" + textBox1.Text + "' and password='" + textBox2.Text + "'", con1);
SqlDataReader dr = cmd.ExecuteReader();
string userText = textBox1.Text;
string passText = textBox2.Text;
while (dr.Read())
{
if (this.CompareStrings(dr["username"].ToString(), userText) &&
this.CompareStrings(dr["password"].ToString(), passText))
{
SqlCommand cmd2 = new SqlCommand("UPDATE login SET password='" + textBox3.Text + "'where username='" + textBox1.Text + "'", con1);
cmd2.ExecuteNonQuery();
MessageBox.Show("Password Changed Successfully");
}
else
{
MessageBox.Show("Incorrect Old password");
}
}
dr.Close();
con1.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
You cannot execute a command while a SqlDataReader is open on the same connection. You can do either of the two following things to change your code:
Create a second connection and run the update query on that second connection.
Store the data from the reader, close the reader and later update all data. In your case, you could store all usernames to update and update them in one update query using Username in (<yourlisthere>)
When you open a DataReader the connection serves only the requests coming from the DataReader. The SqlCommand used to Update the login table cannot run.
Unless you add this to your connectionstring
MultipleActiveResultSets = True;
Here you can find the reference to MARS
And here the words from MSDN about the DataReader
While the SqlDataReader is being used, the associated SqlConnection is
busy serving the SqlDataReader, and no other operations can be
performed on the SqlConnection other than closing it. This is the case
until the Close method of the SqlDataReader is called. For example,
you cannot retrieve output parameters until after you call Close.
As a side note, but very important. Do not use string concatenation to build sql commands. Use always a parameterized query
string cmdText = "UPDATE login SET password=#pwd where username=#usr";
using(SqlCommand cmd2 = new SqlCommand(cmdText, con1))
{
cmd2.Parameters.AddWithValue("#pwd", textBox3.Text);
cmd2.Parameters.AddWithValue("#usr", textBox1.Text);
cmd2.ExecuteNonQuery();
}
A parameterized query will avoid Sql Injection problems and let you simplify your command text.
This is true also for the SELECT query at the beginning of your code. Do not trust the input coming from your user
Another problem that you should be aware of is the storing of clear text passwords in your database. This is considered a very bad practice from a security point of view. You should apply an hash function to you password and store the result. While checking for the correct password you repeat the hash function on the user input and check the result against the hashed password stored in database

SQL delete command?

I am having trouble with a simple DELETE statement in SQL with unexpected results , it seems to add the word to the list??. Must be something silly!. but i cannot see it , tried it a few different ways. All the same result so quite confused.
public void IncludeWord(string word)
{
// Add selected word to exclude list
SqlConnection conn = new SqlConnection();
String ConnectionString = "Data Source = dev\\SQLEXPRESS ;" + "Initial Catalog=sml;" + "User id=** ;" + "Password =*;" + "Trusted_Connection=No";
using (SqlConnection sc = new SqlConnection(ConnectionString))
{
try
{
sc.Open();
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'" +
conn);
Command.Parameters.AddWithValue("#word", word);
Command.ExecuteNonQuery();
}
catch (Exception e)
{
Box.Text = "SQL error" + e;
}
finally
{
sc.Close();
}
ExcludeTxtbox.Text = "";
Box.Text = " Word : " + word + " has been removed from the Exclude List";
ExcludeLstBox.AppendDataBoundItems = false;
ExcludeLstBox.DataBind();
}
Try removing the single quotes. Also why are you concatenating your SQL string with a connection object (.. word='#word'" + conn)???
Try like this:
try
{
using (var sc = new SqlConnection(ConnectionString))
using (var cmd = sc.CreateCommand())
{
sc.Open();
cmd.CommandText = "DELETE FROM excludes WHERE word = #word";
cmd.Parameters.AddWithValue("#word", word);
cmd.ExecuteNonQuery();
}
}
catch (Exception e)
{
Box.Text = "SQL error" + e;
}
...
Notice also that because the connection is wrapped in a using block you don't need to Close it in a finally statement. The Dispose method will automatically call the .Close method which will return the connection to the ADO.NET connection pool so that it can be reused.
Another remark is that this IncludeWord method does far to many things. It sends SQL queries to delete records, it updates some textboxes on the GUI and it binds some lists => methods like this should be split in separate so that each method has its own specific responsibility. Otherwise this code is simply a nightmare in terms of maintenance. I would very strongly recommend you to write methods that do only a single specific task, otherwise the code quickly becomes a complete mess.
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'" +
conn);
should be replaced with
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word='#word'",
conn);
Also try by removing single quotes as suggested by others like this
SqlCommand Command = new SqlCommand(
"DELETE FROM excludes WHERE word=#word",
conn);
The #Word should not be in quotes in the sql query.
Not sure why you're trying to add the connection on the end of the sql query either.
To debug this, examine the CommandText on the SqlCommand object. Before reading further, you should try this.
The issue comes with adding the single quotes around a string that is parameterized. Remove the single quotes and life is beautiful. :-)
Oh, and your conn is an object and needs a comma, not a +.
See the code below:
private void button4_Click(object sender, EventArgs e)
{
String st = "DELETE FROM supplier WHERE supplier_id =" + textBox1.Text;
SqlCommand sqlcom = new SqlCommand(st, myConnection);
try
{
sqlcom.ExecuteNonQuery();
MessageBox.Show("delete successful");
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
}
private void button6_Click(object sender, EventArgs e)
{
String st = "SELECT * FROM supplier";
SqlCommand sqlcom = new SqlCommand(st, myConnection);
try
{
sqlcom.ExecuteNonQuery();
SqlDataReader reader = sqlcom.ExecuteReader();
DataTable datatable = new DataTable();
datatable.Load(reader);
dataGridView1.DataSource = datatable;
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
}
See the code below:
String queryForUpdateCustomer = "UPDATE customer SET cbalance=#txtcustomerblnc WHERE cname='" + searchLookUpEdit1.Text + "'";
try
{
using (SqlCommand command = new SqlCommand(queryForUpdateCustomer, con))
{
command.Parameters.AddWithValue("#txtcustomerblnc", txtcustomerblnc.Text);
con.Open();
int result = command.ExecuteNonQuery();
// Check Error
if (result < 0)
MessageBox.Show("Error");
MessageBox.Show("Record Update of Customer...!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
con.Close();
loader();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
con.Close();
}
You can also try the following if you don't have access to some of the functionality prescribed above (due, I believe, to older versions of software):
using (var connection = _sqlDbContext.CreatSqlConnection())
{
using (var sqlCommand = _sqlDbContext.CreateSqlCommand())
{
sqlCommand.Connection = connection;
sqlCommand.CommandText = $"DELETE FROM excludes WHERE word = #word";
sqlCommand.Parameters.Add(
_sqlDbContext.CreateParameterWithValue(sqlCommand, "#word", word));
connection.Open();
sqlCommand.ExecuteNonQuery();
}
}
...
I'm an associate dev. Hence the "I believe" above.

Categories

Resources