Show a data from database to a label - c#

I'm new to c# programming and have a problem retrieving data from database to a label text. Here is the code what I was trying to do.
private void label3_Click_1(object sender, EventArgs e)
{
MySqlConnection con = new MySqlConnection("Server=localhost; Database=car_rental; user=root; Pwd=; SslMode=none");
DataTable dTable = new DataTable();
con.Open();
MySqlDataReader dr = null;
MySqlCommand cmd = new MySqlCommand("Select * from login where username=" + username, con);
dr =cmd.ExecuteReader();
while (dr.Read())
{
label3.Text = (dr["username"].ToString());
}
con.Close();
}

The problem in your code is created by the concatenation of a string (username) to another string (the sql query). This is a well known source of problems, going from syntax errors (the engine is not able to parse correctly the query text) to a much worse problem known as Sql Injection.
The well known solution is to use parameters instead of concatenated strings
private void label3_Click_1(object sender, EventArgs e)
{
using(MySqlConnection con = new MySqlConnection("Server=localhost; Database=car_rental; user=root; Pwd=; SslMode=none"))
{
con.Open();
// A single string with a parameter placeholder
string sqlCmd = "Select * from login where username=#name";
using(MySqlCommand cmd = new MySqlCommand(sqlCmd, con))
{
// Associate a value to the required parameter
cmd.Parameters.Add("#name", MySqlDbType.VarChar).Value = username;
using(MySqlDataReader dr =cmd.ExecuteReader())
{
// Supposing you have just one user with that name
if(dr.Read())
{
label3.Text = dr["username"].ToString();
}
else
{
label3.Text = "User not found!";
}
}
}
}
Notice how I have added the using statement around each disposable object required to query the database. This statement ensures that the objects involved are disposed at the end of their use freeing the valuable unmanaged resource kept during their usage.

Related

Refresh DataGridView after inserting values

I have established connection and inserted values into the table.
However, I am not sure the best method to refresh the DataGridview as the values have been inserted after click button.
private void button1_Click(object sender, EventArgs e)
{
{
string theText = makeTextBox.Text;
string theText2 = modelTextBox.Text;
var value = Convert.ToInt32(yearTextBox.Text);
int i = 6;
cnn.Open();
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = cnn;
cmd.CommandText = "INSERT INTO cars(Make,Model,Year) VALUES(#Make,#Model,#Year)";
cmd.Prepare();
cmd.Parameters.AddWithValue("#Make", theText);
cmd.Parameters.AddWithValue("#Model", theText2);
cmd.Parameters.AddWithValue("#Year", value);
cmd.ExecuteNonQuery();
{
}
dataGridView1.DataSource = carsBindingSource;
dataGridView1.Refresh();
cnn.Close();
}
}
}
}
enter image description here
EDIT:
here is the code with the working solution of rebinding the datasource and then it will update:
{
string theText = textBox1.Text;
string theText2 = textBox2.Text;
var value = Convert.ToInt32(textBox3.Text);
int i = 6;
cnn.Open();
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = cnn;
cmd.CommandText = "INSERT INTO cars(Make,Model,Year) VALUES(#Make,#Model,#Year)";
cmd.Prepare();
cmd.Parameters.AddWithValue("#Make", theText);
cmd.Parameters.AddWithValue("#Model", theText2);
cmd.Parameters.AddWithValue("#Year", value);
cmd.ExecuteNonQuery();
{
}
cnn.Close();
carsBindingSource = new BindingSource();
carsBindingSource.DataSource = carsTableAdapter.GetData();
dataGridView2.DataSource = carsBindingSource;
}
}```
Your code is missing the part where the carsBindingSource variable is initialized with data. From your limited code, it should be noted that… if you add/insert a new row into the table in the data base, then this is NOT going to automatically update the carsBindingSource.
It is unknown “what” is used as a DataSource to the carsBindingSource. OR, how this data source is populated. I will assume the DataSource to the BindingSource is a DataTable and that somewhere in the code it is getting this DataTable from a query to the data base. If this process is not already in a single method that returns a DataTable, then, I recommend you create one, and it may look something like…
private DataTable GetCarsDT() {
DataSet ds = new DataSet();
string connString = "Server = localhost; Database = CarsDB; Trusted_Connection = True;";
try {
using (SqlConnection conn = new SqlConnection(connString)) {
conn.Open();
using (SqlCommand command = new SqlCommand()) {
command.Connection = conn;
command.CommandText = "SELECT * FROM Cars";
using (SqlDataAdapter da = new SqlDataAdapter(command)) {
da.Fill(ds, "Cars");
return ds.Tables[0];
}
}
}
}
catch (Exception ex) {
MessageBox.Show("DBError:" + ex.Message);
}
return null;
}
Above will return a DataTable with three (3) columns, Make, Model and Year. This DataTable is used as a DataSource to the BindingSource… carsBindingBource.
Now in the button1_Click event, the code inserts the new values into the data base. However, the carsBindingSource will still contain the data “before” the new items were added to the DB. Therefore, we can simply use the method above to “update” the carsBindingSource after the new items are added to the DB.
Note: you can go two routs here, 1) as described above, simply update “all” the data in the binding source… OR … 2) after updating the new items into the data base, you can also add the new items to the binding source’s data source… i.e. its DataTable. Either way will work and unless there is a large amount of data, I do not think one way would be preferred over the other.
Below shows what is described above. Note, the commented code adds the new items directly to the DataTable. You can use either one but obviously not both.
private void button1_Click(object sender, EventArgs e) {
string connString = "Server = localhost; Database = CarsDB; Trusted_Connection = True;";
try {
using (SqlConnection conn = new SqlConnection(connString)) {
conn.Open();
using (SqlCommand command = new SqlCommand()) {
command.Connection = conn;
command.CommandText = "INSERT INTO cars(Make,Model,Year) VALUES(#Make,#Model,#Year)";
command.Parameters.Add("#Make", SqlDbType.NChar, 50).Value = makeTextBox.Text.Trim();
command.Parameters.Add("#Model", SqlDbType.NChar, 50).Value = modelTextBox.Text.Trim();
int.TryParse(yearTextBox.Text.Trim(), out int year);
command.Parameters.Add("#Year", SqlDbType.Int).Value = year;
command.ExecuteNonQuery();
carsBindingSource.DataSource = GetCarsDT();
//DataTable dt = (DataTable)carsBindingSource.DataSource;
//dt.Rows.Add(makeTextBox.Text.Trim(), modelTextBox.Text.Trim(), year);
}
}
}
catch (Exception ex) {
MessageBox.Show("DBError:" + ex.Message);
}
}
Putting all this together…
BindingSource carsBindingSource;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
carsBindingSource = new BindingSource();
carsBindingSource.DataSource = GetCarsDT();
dataGridView1.DataSource = carsBindingSource;
}
Hope this makes sense.
I dont think its possible. You may need to create a separate button to submit and then refresh the data

c# System.InvalidOperationException: 'The connection is already open.'

I'm coding a Windows Forms login page for an administration application. My problem is, that when I try to log on, I get the error message
System.InvalidOperationException: 'The connection is already open.'
Any help would be appreciated
public partial class Form1 : Form
{
MySqlConnection con = new MySqlConnection (#"Database= app2000; Data Source = localhost; User = root; Password =''");
int i;
public Form1()
{
InitializeComponent();
}
private void btnClose_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void btnLogin_Click(object sender, EventArgs e)
{
i = 0;
con.Open();
MySqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM adminlogin WHERE username='" + txtBoxUsername + "'AND password='" + txtBoxPassword + "'";
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
i = Convert.ToInt32(dt.Rows.Count.ToString());
if (i == 0)
{
lblerrorInput.Show();
}
else
{
this.Hide();
Main ss = new Main();
ss.Show();
}
}
}
Do not cache Connection, it's a typical antipattern, but recreate it when you need it
public partial class Form1 : Form {
...
//DONE: Extract method
private static bool UserExists(string userName, string password) {
//DONE: Do not cache connections, but recreate them
using (MySqlConnection con = new MySqlConnection (#"...") {
con.Open();
//DONE: wrap IDisposable into using
using (MySqlCommand cmd = con.CreateCommand()) {
cmd.CommandType = CommandType.Text;
//DONE: Make query being readable
//DONE: Make query being parametrized
cmd.CommandText =
#"SELECT *
FROM adminlogin
WHERE username = #UserName
AND password = #PassWord"; // <- A-A-A! Password as a plain text!
//TODO: the simplest, but not the best solution:
// better to create parameters explicitly
// cmd.Parameters.Add(...)
cmd.Parameters.AddWithValue("#UserName", txtBoxUsername);
cmd.Parameters.AddWithValue("#PassWord", txtBoxPassword);
// If we have at least one record, the user exists
using (var reader = cmd.ExecuteReader()) {
return (reader.Read());
}
}
}
}
Finally
private void btnLogin_Click(object sender, EventArgs e) {
if (!UserExists(txtBoxUsername.Text, txtBoxPassword.Text))
lblerrorInput.Show();
else {
Hide();
Main ss = new Main();
ss.Show();
}
}
You forgot to close the connection, use con.Close() at the end to close the connection and avoid this error the next time the event fires.
There are some mistakes in your code.
You should close the sql connection when you finished your process.
I suggest you to use using statement to dispose connection instance after complete database actions.
Also, you should use command parameters to prevent Sql injection.
You can declare connection string like this;
private string _connectionString = #"Database= app2000; Data Source = localhost; User = root; Password =''";
The method part looks like;
using (var con = new MySqlConnection(_connectionString))
{
i = 0;
con.Open();
MySqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT * FROM adminlogin WHERE username = #username and password = #password";
cmd.Parameters.AddWithValue("#username", txtBoxUsername);
cmd.Parameters.AddWithValue("#password", txtBoxPassword);
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
i = Convert.ToInt32(dt.Rows.Count.ToString());
if (i == 0)
{
lblerrorInput.Show();
}
else
{
this.Hide();
Main ss = new Main();
ss.Show();
}
con.Close();
}
First, don't cache your Connection objects. It's a terrible practice and I've had to go back and fix it every time I accept a new job and inherit code. Most database access classes implement IDisposable, so use using and take advantage of it to keep your code clean. FYI, Readers and Adapters are also IDisposable so you can do the same with them, too.
string command = "select stuff from mydata";
string connection = GetConnectionStringFromEncryptedConfigFile();
using (var conn = new SqlConnection(connection))
{
using (var cmd = new SqlCommand(command, conn))
{
cmd.Connection.Open();
//do stuff
}
}
Second, if you're forced to use a cached connection (i.e., you inherited horrible code and don't have time to fix it yet), check your State first.
if(conn.State != System.Data.ConnectionState.Open)
{
conn.Open();
}
Note that there are a lot more states than just Open and Closed, and if you try to open a connection that is busy, you'll still get errors. It's still a much wiser approach to use the IDisposable implementations with using so you don't have to worry about this sort of thing so much.

C# Windows Forms Application - display sql server values in textbox

I need assistance to display sql server values in a windows forms. In the application below if the query returns a row then the values are displayed. I understand that I am to use sqldatareader but so far I have been unsuccessful how to add it.
SqlConnection ChuoDB_Connection = new SqlConnection("Data Source=test-PC\\tester;Initial Catalog=Chuo;Integrated Security=True;Pooling=False");
SqlDataAdapter select_adapt;
private void btn_guardian_student_search_Click(object sender, EventArgs e)
{
if (rd_btn_guardian_student_no.Checked == true)
{
DataSet ds = new DataSet();
SqlDataReader dr;
ChuoDB_Connection.Open();
select_adapt = new SqlDataAdapter("SELECT * FROM Guardian WHERE STUDENT_NO = #student_no", ChuoDB_Connection);
select_adapt.SelectCommand.Parameters.Add("#student_no", SqlDbType.Int).Value = Convert.ToInt32(txt_bx_guardian_student_search.Text);
select_adapt.Fill(ds);
if (ds.Tables[0].Rows.Count == 0)
{
lbl_guardian_student_search.Text = "No Guardian record exists for this student. Please enter the Guardian Information";
ChuoDB_Connection.Close();
}
if (ds.Tables[0].Rows.Count > 0)
{
lbl_guardian_student_search.Text = "";
while (dr.read())
{
txtBox1.Text = rdr.Item["DBFieldName1"].ToString();
txtBox2.Text = rdr.Item["DBFieldName2"].ToString();
}
}
}
}
I think you do not need DataAdapter and DataSet here.
Try just with the DataReader:
string _connectionString = "Data Source=test-PC\\tester;Initial Catalog=Chuo;Integrated Security=True;Pooling=False";
string _selectCommand = #"SELECT * FROM Guardian WHERE STUDENT_NO = #student_no";
here code for the click handler:
SqlParameter parameter = new SqlParameter("#student_no", SqlDbType.Int);
parameter.Value = Convert.ToInt32(txt_bx_guardian_student_search.Text);
using (IDbConnection connection = new SqlConnection(_connectionString))
{
connection.Open();
using (IDbCommand command = connection.CreateCommand())
{
command.Connection = connection;
command.CommandText = _selectCommand;
command.Parameters.Add("#student_no", SqlDbType.Int).Value = Convert.ToInt32(txt_bx_guardian_student_search.Text);
IDataReader reader = command.ExecuteReader();
if (reader.Read())
{
txtBox1.Text = reader["DBFieldName1"].ToString();
txtBox2.Text = reader["DBFieldName2"].ToString();
}
else
{
lbl_guardian_student_search.Text = "No Guardian record exists for this student. Please enter the Guardian Information";
}
}
}
To use a SqlDataReader you need to initialize it using the ExecuteReader method of a SqlCommand. So in your code you could discard all the part relative to the SqlDataAdapter
private void btn_guardian_student_search_Click(object sender, EventArgs e)
{
if (rd_btn_guardian_student_no.Checked == true)
{
using(SqlConnection cnn = new SqlConnection(......))
using(SqlCommand cmd = new SqlCommand(#"SELECT * FROM Guardian
WHERE STUDENT_NO = #student_no", cnn))
{
cnn.Open();
cnn.Add("#student_no", SqlDbType.Int).Value = Convert.ToInt32(txt_bx_guardian_student_search.Text);
using(SqlDataReader rd = new cmd.ExecuteReader())
{
if(!rd.HasRows)
lbl_guardian_student_search.Text = "No Guardian record exists for this student. Please enter the Guardian Information";
else
{
rdr.Read();
txtBox1.Text = rdr.Item["DBFieldName1"].ToString();
txtBox2.Text = rdr.Item["DBFieldName2"].ToString();
}
}
}
}
}
Note that I have moved the global connection object inside the code making it a local variable that is initialized inside a using block as well the command and the reader. They are disposable objects and should be disposed when you have finished with them. The Using Statement ensure correct dispose of these objects
Also note that keeping a connection opened all the time of your application is really a big NO-NO in database server applications. You hinder the server ability to serve more requests if you keep your connection constantly open. And there is no great penalty in restoring the server connection because ADO.NET has an infrastructure called Connection Pooling that allows you to restore your connection immediately

How Do I Populate Text Boxes With Sql Database Data Using One Combo Box

Hey everyone pretty new to SQL Database functions but have been coding in c# for about a year now still not that great at it but I'm getting there!
I'm currently creating a football application and to Edit players and Matches i was wanting to use one drop down combo box to retrieve data from an SQL database which then would populate other text boxes and combo boxes. I've had a go at it myself but don't know where i'm going wrong.
On form load my connection opens i populate my datasets and i execute this method to populate my combobox
private void Navigate()
{
string showPlayers = "SELECT * From Add_Players";
SqlCommand cmdData = new SqlCommand(showPlayers, conn);
SqlDataReader myReader = cmdData.ExecuteReader();
while (myReader.Read())
{
comboEditPlayer.Items.Add(myReader[0]);
}
conn.Close();
}
After which in the combo box selected index changed method i have this code
private void comboEditPlayer_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
conn.Open();
string showPlayers = "SELECT * From Add_Players WHERE Player_ID ='"
+ comboEditPlayer + "' ;";
SqlCommand cmdData = new SqlCommand(showPlayers, conn);
SqlDataReader myReader = cmdData.ExecuteReader();
while (myReader.Read())
{
comboEditPlayerPos.Items.Add(myReader[1]);
txtEditPlayerName.Text = myReader[2].ToString();
txtEditPlayerSecond.Text = myReader[3].ToString();
comboEditPlayerStatus.Items.Add(myReader[4]);
}
conn.Close();
conn.Dispose();
}
catch (Exception comboFail)
{
MessageBox.Show(comboFail.ToString());
}
}
I've been told this code is open and i need to use parameterized queries for preventing hacker attempts which i have started but do not know what Parameter i should be adding to the code i have for this is below
private void comboEditPlayer_SelectedIndexChanged(object sender, EventArgs e)
{
string connectionString =
ZimbFootball.Properties.Settings.Default.Football2ConnectionString;
using (SqlConnection connection = new SqlConnection (connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(
"SELECT * From Add_Players WHERE Player_ID ="
+ comboEditPlayer.SelectedValue + "", connection))
{
command.Parameters.Add(new SqlParameter ("",));
}
}
}
All help is appreciated and please go easy on me :P
You could add a parameter to the collection with the value of your ComboBox, then execute the query and read back the values from the reader
private void comboEditPlayer_SelectedIndexChanged(object sender, EventArgs e)
{
string connectionString =
ZimbFootball.Properties.Settings.Default.Football2ConnectionString;
using (SqlConnection connection = new SqlConnection (connectionString))
using (SqlCommand command = new SqlCommand(
"SELECT * From Add_Players WHERE Player_ID =#id", connection))
{
connection.Open();
command.Parameters.AddWithValue("#id", comboEditPlayer.Text);
using(SqlDataReader myReader = command.ExecuteReader())
{
while (myReader.Read())
{
comboEditPlayerPos.Items.Add(myReader[1]);
txtEditPlayerName.Text = myReader[2].ToString();
txtEditPlayerSecond.Text = myReader[3].ToString();
comboEditPlayerStatus.Items.Add(myReader[4]);
}
}
}
}

What is the optimal / standard method of using a sql connection?

protected void populateDataGrid()
{
string connectionString = configurationManager.ConnectionStrings["myConnectionString"].ConnectionString;
string command = "select * from student";
SqlDataAdapter dataAdapter = new SqlDataAdapter(command, connectionString);
DataSet data = new DataSet();
dataAdapter.Fill(data);
GridView1.DataSource = data;
GridView1.DataBind();
}
protected void Button2_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["sqlstudentConnectionString"].ConnectionString;
string command = #"INSERT INTO [student] (studentID, studentFirstName, studentLastName)
VALUES (" + TextID.Text + ", '" + TextFirstName.Text + "', '" + TextLastName.Text + "')";
SqlConnection sqlConnection = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand();
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = command;
cmd.Connection = sqlConnection;
sqlConnection.Open();
cmd.ExecuteNonQuery();
sqlConnection.Close();
TextID.Text = "";
TextFirstName.Text = "";
TextLastName.Text = "";
populateDataGrid();
}
The first function gets all the table data and dumps it to a gridview.
The second function takes input and inserts it into the database.
How can these functions be condensed or simplified?
How can these functions be condensed or simplified?
I would focus on correctness before simplification. Currently I can see at least two problems with the code:
You should absolutely use parameterized SQL instead of putting the values into the SQL itself. Your current code is prone to SQL injection attacks.
You should use using statements so that connection and command are both closed automatically even if exceptions are thrown.
Then in terms of simplification:
You can use the SqlCommand constructor which takes the text and connection - the type defaults to Text anyway.
I would personally try to separate the UI code from the storage code, at least for a non-trivial project. You should look at ASP.NET MVC, at least to get some idea of separation, even if you don't change to start using it.
In Button2_Click(object sender, EventArgs e) method , you need to use parametrized query to avoid SQL Injection.
That is the standard way.
protected void Button2_Click(object sender, EventArgs e)
{
string connectionString = ConfigurationManager.ConnectionStrings["sqlstudentConnectionString"].ConnectionString;
string command = #"INSERT INTO [student] (
studentID, studentFirstName, studentLastName
) VALUES (
#studID, #FName, #LName
)";
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandType = System.Data.CommandType.Text;
cmd.CommandText = command;
cmd.Parameters.AddWithValue("#studID", TextID.Text);
cmd.Parameters.AddWithValue("#FName", TextFirstName.Text);
cmd.Parameters.AddWithValue("#LName", TextLastName.Text);
cmd.Connection = sqlConnection;
sqlConnection.Open();
cmd.ExecuteNonQuery();
sqlConnection.Close();
}
TextID.Text = "";
TextFirstName.Text = "";
TextLastName.Text = "";
populateDataGrid();
}
Hope Its Helpful.

Categories

Resources