I am writing a program to add information from a Form into my database, however, when running the program I am met with the following syntax error:
System.InvalidOperationException: 'Invalid attempt to call Read when reader is closed.'
If I don't close the reader the statement sqlCmd.ExecuteNonQuery(); will not be run as there is already an open DataReader associated with this Command.
Here is the source:
string isbnQuery = "SELECT * FROM book WHERE isbn = '" + txtbox_id.Text + "'";
SqlConnection sqlCon = new SqlConnection(connectionString);
SqlCommand sqlCmdQuery = new SqlCommand(isbnQuery, sqlCon);
SqlDataAdapter sda = new SqlDataAdapter(isbnQuery, sqlCon);
DataTable dtbl = new DataTable();
sda.Fill(dtbl);
if (dtbl.Rows.Count == 1)
{
try
{
using (sqlCon)
{
sqlCon.Open();
SqlDataReader reader = sqlCmdQuery.ExecuteReader();
while (reader.Read())
{
DialogResult dr = MessageBox.Show("Is this Correct?", reader["title"].ToString(), MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
{
SqlCommand sqlCmd = new SqlCommand("book_log", sqlCon);
sqlCmd.CommandType = CommandType.StoredProcedure;
// adding text-field data to the database
char current = 'N';
sqlCmd.Parameters.AddWithValue("#book_id", reader["book_id"]);
sqlCmd.Parameters.AddWithValue("#id", ID.getID);
sqlCmd.Parameters.AddWithValue("#date_from", dtp_from.Value.ToString());
sqlCmd.Parameters.AddWithValue("#date_to", dtp_hand.Value.ToString());
sqlCmd.Parameters.AddWithValue("#fine", current);
sqlCmd.Parameters.AddWithValue("#handed", current);
sqlCmd.ExecuteNonQuery();
MessageBox.Show("Done!");
}
else if (dr == DialogResult.No)
{
return;
}
}
}
}
catch (SqlException ex)
{
MessageBox.Show("Contact a Staff Member " + ex.Message);
}
finally
{
sqlCon.Close();
}
}
else
{
Console.WriteLine("Book Not Found");
}
}
Related
I am trying to make a login at the moment. I watched some videos and found a good way. Every user has an id, Username and Password. I want to get the id of the user who has just been logged in and save it in an Integer. I also tried it with an ExecuteReader but I get an Exception(MySql.Data.MySqlClient.MySqlException).
My current Code is:
try
{
if (sqlCon.State == ConnectionState.Closed)
{
sqlCon.Open();
}
string query = "SELECT COUNT(1) FROM Users_Table WHERE Username=#Username AND Password=#Password;";
MySqlCommand sqlCmd = new MySqlCommand(query, sqlCon);
sqlCmd.Parameters.AddWithValue("#Username", maintxtbox1.Text);
sqlCmd.Parameters.AddWithValue("#Password", Hashed_Password);
int count = Convert.ToInt32(sqlCmd.ExecuteScalar());
if (count == 1)
{
//Login correct
}
else
{
//Login incorrect
}
}
catch
{
//Exception
}
finally
{
sqlCon.Close();
}
The try with the ExecuteReader:
try
{
if (sqlCon.State == ConnectionState.Closed)
{
sqlCon.Open();
}
string query = "SELECT id,Username,Password FROM Users_Table WHERE Username=#Username AND Password=#Password;";
MySqlCommand sqlCmd = new MySqlCommand(query, sqlCon);
sqlCmd.Parameters.AddWithValue("#Username", maintxtbox1.Text);
sqlCmd.Parameters.AddWithValue("#Password", Hashed_Password);
MySqlDataReader datareader = sqlCmd.ExecuteReader();
if (datareader.HasRows)
{
MessageBox.Show("Test: " + datareader.GetString("id"));
}
else
{
//Login incorrect
}
}
catch
{
//Exception
}
finally
{
sqlCon.Close();
}
I hope somebody can help me. Thank you in advance.
Try and use the Read method:
if(datareader.Read()){
MessageBox.Show("Test: "+datareader.GetString(0));
}
EDIT:
To make good use and disposal of resources I recommend using the MySqlDataReader inside a using block, e.j.
using(MySqlDataReader reader = new sqlCmd.ExecuteReader()){
if(reader.Read()){
MessageBox.Show("Test: "+reader.GetString(0));
}
}
I found a solution to my Question by myself. I forgot the while(datareader.Read()) in the ìf(datareader.HasRows) query. Here is my working Code:
try
{
if (sqlCon.State == ConnectionState.Closed)
{
sqlCon.Open();
}
string query = "SELECT * FROM Users_Table WHERE username=#Username AND password=#Password;";
MySqlCommand sqlCmd = new MySqlCommand(query, sqlCon);
sqlCmd.Parameters.AddWithValue("#Username", maintxtbox1.Text);
sqlCmd.Parameters.AddWithValue("#Password", Hashed_Password);
MySqlDataReader datareader = sqlCmd.ExecuteReader();
if (datareader.HasRows)
{
while (datareader.Read())
{
UserID = datareader.GetInt32("id");
}
}
else
{
//Incorrect Password
}
}
catch
{
//Error
}
finally
{
sqlCon.Close();
}
Now I have a combobox i choose "Name" and input some text. I have query data from my database. but now i don't know how to load data into datagridview.
This is my code button Search:
private void btnSearch_Click(object sender, EventArgs e)
{
String strSearch = txtSearch.Text.Trim();
String Selected = cbSearch.GetItemText(cbSearch.SelectedItem);
switch (Selected)
{
case "All Search":
LoadData();
break;
case "Name":
try
{
if (conn.State == ConnectionState.Open)
conn.Close();
MySqlCommand cmd = new MySqlCommand("Select * FROM sinhvien where name LIKE #name");
cmd.Connection = conn;
cmd.Connection.Open();
cmd.Parameters.Add(new MySqlParameter("#name", "%" + txtSearch.Text + "%"));
cmd.ExecuteNonQuery();***//I dont't know what to do after query here***
MessageBox.Show("Delete this row successfully!\n",
"Notification", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (MySqlException)
{
MessageBox.Show("Error load data from database!","Notification", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
break;
break;
}
}
then how to load data from database into datagridview:
private void LoadData()
{
try
{
conn = new MySqlConnection(connString);
if (conn.State == ConnectionState.Open)
conn.Close();
daSinhVien = new MySqlDataAdapter("SELECT * FROM sinhvien", conn);
dtSinhVien = new DataTable();
dtSinhVien.Clear();
daSinhVien.Fill(dtSinhVien);
dgvSinhVien.DataSource = dtSinhVien;
}
catch (MySqlException)
{
MessageBox.Show("Can't not load data from sinhvien!!","Notification",MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
cbSearch.Items.Add("All Search");
cbSearch.Items.Add("Name");
cbSearch.Items.Add("Age");
cbSearch.Items.Add("Class");
cbSearch.Items.Add("Address");
}
Why are you using cmd.ExecuteNonQuery();?
That's for executing statements that you don't expect to have data returning - like a command that adjusts some records.
Instead, you might be looking for something like:
SqlConnection sqlConnection1 = new SqlConnection("Your Connection String");
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = "SELECT * FROM Customers";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
reader = cmd.ExecuteReader();
// Data is accessible through the DataReader object here.
sqlConnection1.Close();
... this is off the MSDN page: https://msdn.microsoft.com/en-us/library/fksx3b4f.aspx
im doing an update statement where the datetimepicker(logout) will insert into the same row as login but its making another row when i logout here is the link : http://imgur.com/a/rAWhi
ps. the problem here is the logout button is inserting into another row.. but i want to insert it in the same row.
here is my code :
private void button1_Click(object sender, EventArgs e)
{
con.Open();
MySqlCommand cmd = con.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select * from empinfo where username = '" + label4.Text + "' and IDNUMBER = '" + textBox1.Text + "' ";
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
i = Convert.ToInt32(dt.Rows.Count.ToString());
if (string.IsNullOrEmpty(textBox1.Text))
{
MessageBox.Show("Input your id number");
}
else if (i == 0)
{
MessageBox.Show("Username and IDNUMBER didn't match.", "Log-In Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else
{
updateuser();
login frmm = new login();
frmm.Show();
this.Close();
}
con.Close();
}
public void updateuser()
{
MySqlConnection cnn = new MySqlConnection(mysqlAddress);
MySqlCommand cmdupdate;
cnn.Open();
try
{
cmdupdate = cnn.CreateCommand();
cmdupdate.CommandText = "update employee set logout = #logout";
cmdupdate.CommandText = "Insert into employee (logout) values (#logout)";
cmdupdate.Parameters.AddWithValue("#logout", dateTimePicker1.Value);
cmdupdate.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
if (cnn.State == ConnectionState.Open)
{
cnn.Close();
MessageBox.Show("Data has been saved");
}
}
}
As #Ben in the comments pointed out, you do not need to use insert and only want update so change your code like this:
try
{
cmdupdate = cnn.CreateCommand();
cmdupdate.CommandText = "update employee set logout=#logout";
cmdupdate.CommandText += "WHERE IDNUMBER=#IDNUMBER";
cmdupdate.Parameters.AddWithValue("#IDNUMBER", textBox1.Text.Trim());
cmdupdate.Parameters.AddWithValue("#logout", dateTimePicker1.Value);
cmdupdate.ExecuteNonQuery();
}
The Where is to make sure it only updates the IDNUMBER on the textbox.
I think you should create different methods for login and logout like
For LOGIN
public static long id;
public void loginuser()
{
MySqlConnection cnn = new MySqlConnection(mysqlAddress);
MySqlCommand cmd;
cnn.Open();
try
{
cmd = cnn.CreateCommand();
cmd.CommandText = "Insert into employee (logout) values (#logout)";
cmd.Parameters.AddWithValue("#login", DateTime.Now);
cmd.ExecuteNonQuery();
id = cmd.LastInsertedId; // it will return the id of last inserted row
}
catch (Exception)
{
throw;
}
finally
{
if (cnn.State == ConnectionState.Open)
{
cnn.Close();
MessageBox.Show("Data has been saved");
}
}
}
For LOGOUT
public void logoutuser()
{
MySqlConnection cnn = new MySqlConnection(mysqlAddress);
MySqlCommand cmd;
cnn.Open();
try
{
cmd = cnn.CreateCommand();
cmd.CommandText = "update employee set logout = #logout WHERE IDNUMBER=#ID";
cmd.Parameters.AddWithValue("#logout", dateTimePicker1.Value);
cmd.Parameters.AddWithValue("#ID", id);
cmd.ExecuteNonQuery();
}
catch (Exception)
{
throw;
}
finally
{
if (cnn.State == ConnectionState.Open)
{
cnn.Close();
MessageBox.Show("Data has been saved");
}
}
}
For some reason result is always -1 and nothing get added to the database. I executed the query in SQL Server and it runs fine. I don't get any exception whatsoever and I don't use any stored procedure.
SqlConnection con = new SqlConnection("Data Source=.\\SQLEXPRESS;Initial Catalog=RAINBOW;Integrated Security=True");
SqlCommand cmd;
cmd = new SqlCommand("INSERT INTO ItemDetails.item(description,category_id) VALUES (#item_desc,#cat_id)", con);
cmd.Parameters.AddWithValue("#item_desc", txtitemdesc.Text);
cmd.Parameters.AddWithValue("#cat_id", GetCategoryID());
try
{
con.Open();
int result = cmd.ExecuteNonQuery();
if (result > 0)
{
MessageBox.Show("Record Inserted Successfully!");
}
else
{
MessageBox.Show("Failed to add record");
}
}
catch (SqlException ex)
{
MessageBox.Show("An error has occured! " + ex);
}
finally
{
con.Close();
}
Edit
int GetCategoryID()
{
int cat_id = 0;
cmd = new SqlCommand("SELECT category_id FROM ItemDetails.category WHERE category_desc=#cat_desc", con);
con.Open();
cmd.Parameters.AddWithValue("#cat_desc", cboCategory.Text);
reader = cmd.ExecuteReader();
while (reader.Read())
{
cat_id = int.Parse(reader["category_id"].ToString());
}
reader.Close();
con.Close();
return cat_id;
}
If possible then don't use AddWithValue(). Actually when you are not providing type explicitly, it will try to convert implicitly and sometimes the implicit conversion may not be the most optimal of conversions. You can find some more discussion in this link.
And most important thing is don't forget to clear parameters before assign, by using this line.
cmd.Parameters.Clears();
Check below code.
string sqlQuery = "INSERT INTO ItemDetails.item(description,category_id) VALUES (#item_desc,#cat_id)";
using (SqlCommand cmd = new SqlCommand(sqlQuery, con))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Clears(); // Add this same line in your getcategory function.
cmd.Parameters.Add("#item_desc", SqlDbType.VarChar, 1000).Value = txtitemdesc.Text;
cmd.Parameters.Add("#cat_id", SqlDbType.Int).Value = GetCategoryID();
try
{
con.Open();
int result = cmd.ExecuteNonQuery();
if (result > 0)
{
MessageBox.Show("Record Inserted Successfully!");
}
else
{
MessageBox.Show("Failed to add record");
}
}
catch (SqlException ex)
{
MessageBox.Show("An error has occured! " + ex);
}
finally
{
con.Close();
}
}
When debugger is applied the query-line shows no data in textBox1.Text.my code is following:
namespace SeparateConnection
{
class clsGridView
{
Connection co2 = new Connection();
//display our global varaible for connection
SqlConnection myconn3 = new SqlConnection("data source=M-SULEMAN-PC;initial catalog=dbmsLogin;integrated security=sspi");
public void Delete()
{
co2.setconn();
try
{
DialogResult result = MessageBox.Show("Are you sure you want to delete ?", "Message",
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
//myconn3.Open();
DataTable table2 = new DataTable();
frmGridView gd = new frmGridView();
SqlDataAdapter myadd2 = new SqlDataAdapter("Delete from tblLogin where UserName ='" + gd.textBox1.Text + "'", myconn3);
myadd2.Fill(table2);
//Sqlcommandbulider to allow changes to database
SqlCommandBuilder mybuild = new SqlCommandBuilder(myadd2);
//Update the database
myadd2.Update(table2);
//Close the connection
myconn3.Close();
}
else
return;
}
catch (Exception error)
{
MessageBox.Show(error.ToString());
}
}
----------when I use the same class for calling and defining the method..there is no problem
To delete data you must follow this pattern:
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "Delete from tblLogin where UserName = #param";
cmd.Parameters.Add("#param", gd.textBox1.Text);
cmd.Connection = conn;
cmd.ExecuteNonQuery();
why dont you try out something like this
string connetionString = null;
SqlConnection connection ;
SqlDataAdapter adapter = new SqlDataAdapter();
string sql = null;
connetionString = "Data Source=ServerName;Initial Catalog=DatabaseName;User ID=UserName;Password=Password";
connection = new SqlConnection(connetionString);
sql = "delete product where Product_name ='Product6'";
try
{
connection.Open();
adapter.DeleteCommand = connection.CreateCommand();
adapter.DeleteCommand.CommandText = sql;
adapter.DeleteCommand.ExecuteNonQuery();
MessageBox.Show ("Row(s) deleted !! ");
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}