I want to get the values from MySQL database and that would need to show the messages according to values. But it does not happen and that will always show int privilege is 0. If I did not assign that default value, errors will be showing on the code.
How can I solve this issue and show messages according to the int privilege values?
private void button_login_Click(object sender, RoutedEventArgs e)
{
string username = usernameInput.Text;
string password = passwordInput.Password;
int privilege = 0;
try
{
//This is command class which will handle the query and connection object.
string Query = "SELECT`tbl_user_login`.`u_id`,`tbl_user_login`.`u_username`,
`tbl_user_login`.`u_password`,`tbl_user_login`.`u_privilege`
FROM `bcasdb`.`tbl_user_login`WHERE `tbl_user_login`.`u_username` = '"
+ username + "' AND `tbl_user_login`.`u_password` ='" + password
+ "' AND `tbl_user_login`.`u_privilege` = #privi;";
MySqlConnection conn =
new MySqlConnection(BCASApp.DataModel.DB_CON.connection);
MySqlCommand cmd = new MySqlCommand(Query, conn);
cmd.Parameters.AddWithValue("#privi", privilege);
MySqlDataReader MyReader;
conn.Open();
MyReader = cmd.ExecuteReader();
// Here our query will be executed and data saved into the database.
if (MyReader.HasRows && this.Frame != null)
{
while (MyReader.Read())
{
if (privilege == 1)
{
DisplayMsgBox("click ok to open the admin page ", "OK");
}
if (privilege == 2)
{
DisplayMsgBox("click ok to open the staff page ", "OK");
}
else
{
DisplayMsgBox("privilege 0", "ok");
}
}
}
else
{
DisplayMsgBox("sucess else", "ok");
}
conn.Close();
}
catch (Exception )
{
DisplayMsgBox("sucess catch", "ok");
}
}
Looks like what you're trying to do is checking the value of u_privilege column from tbl_user_login table instead of making a where condition based on privilege. You need to remove this where condition
AND `tbl_user_login`.`u_privilege` = #privi
and also remove the parameter assignment
cmd.Parameters.AddWithValue("#privi", privilege);
You can get the value of tbl_user_login.u_privilege by using MySqlDataReader.GetInt32 syntax inside while (MyReader.Read()) block
MyReader.GetInt32(3)
Please note that 3 is used because MyReader.GetInt32 requires a zero based index parameter and tbl_user_login.u_privilege is the fourth column from your query. The value should be assigned to privilege variable as below
privilege = MyReader.GetInt32(3)
On a side note, you should parameterize your query to avoid SQL injection. Here's the complete code after implementing the above changes
int privilege = 0;
try
{
//This is command class which will handle the query and connection object.
string Query = "SELECT`tbl_user_login`.`u_id`,`tbl_user_login`.`u_username`,
`tbl_user_login`.`u_password`,`tbl_user_login`.`u_privilege`
FROM `bcasdb`.`tbl_user_login`WHERE `tbl_user_login`.`u_username` =
#username AND `tbl_user_login`.`u_password` = #password;";
MySqlConnection conn =
new MySqlConnection(BCASApp.DataModel.DB_CON.connection);
MySqlCommand cmd = new MySqlCommand(Query, conn);
cmd.Parameters.AddWithValue("#username", username);
cmd.Parameters.AddWithValue("#password", password);
MySqlDataReader MyReader;
conn.Open();
MyReader = cmd.ExecuteReader();
// Here our query will be executed and data saved into the database.
if (MyReader.HasRows && this.Frame != null)
{
while (MyReader.Read())
{
privilege = MyReader.GetInt32(3)
if (privilege == 1)
{
DisplayMsgBox("click ok to open the admin page ", "OK");
}
if (privilege == 2)
{
DisplayMsgBox("click ok to open the staff page ", "OK");
}
else
{
DisplayMsgBox("privilege 0", "ok");
}
}
}
else
{
DisplayMsgBox("sucess else", "ok");
}
conn.Close();
}
catch (Exception )
{
DisplayMsgBox("sucess catch", "ok");
}
If im not wrong, the privilege is being returned as a string type. Try take it in as a string then cast it to an integer?
Related
This question already has answers here:
Check if a record exists in the database
(13 answers)
Closed 4 months ago.
As of now, I can delete a record based on rank without checking if it exists, after that, it will pop up a message "Movie deleted" to notify the user.
protected void bn_delete_Click(object sender, EventArgs e)
{
string rank = tb_rank.Text;
string query = "SELECT * FROM MovieList WHERE Rank= #Rank";
new System.Data.OleDb.OleDbCommand(query, new System.Data.OleDb.OleDbConnection(connectionString));
System.Data.OleDb.OleDbCommand ocmd =
new System.Data.OleDb.OleDbCommand(query,
new System.Data.OleDb.OleDbConnection(connectionString));
ocmd.CommandType = CommandType.Text;
ocmd.CommandText = "DELETE FROM MovieList WHERE Rank= #Rank";
ocmd.Parameters.AddWithValue("#Rank", rank);
ocmd.Connection.Open();
ocmd.ExecuteNonQuery();
ocmd.Connection.Close();
string notification = "Movie deleted";
ClientScript.RegisterStartupScript(this.GetType(), "myalert", "alert('" + notification + "');", true);
}
How can I make sure that the record exists first before deleting it?
If the record does not exist, I want to pop up a message showing "Movie not exists" and do nothing.
Thank you!
Instead of selecting and then deleting, you can use the fact that ExecuteNonQuery() returns an int that represents the number of rows effected by the SQL statement it executed. If it returns 0, it means that no record was deleted.
var rowsEffected = ocmd.ExecuteNonQuery();
var notification = rowsEffected == 0
? "Movie deleted"
: "Movie does not exist" ;
ExecuteNonQuery() returns the number of rows affected see. You could simply check if this integer is 0 and then return the message.
Besides using ExecuteNonQuery you can use ExecuteScalar. This executes the query, and returns the first column of the first row in the result set returned by the query. Additional columns or rows are ignored. The query can be a count and check if the count is larger than 0. Here is a snippet of how your code would look like:
void Main(string[] args)
{
string rank = tb_rank.Text;
if (!MovieExists(rank))
{
// show message
return;
}
DeleteMovie(rank);
}
private bool MovieExists(string rank)
{
string query = "SELECT COUNT(*) FROM MovieList WHERE Rank= #Rank";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
OleDbCommand command = new OleDbCommand(query);
command.Connection = connection;
command.Parameters.AddWithValue("#Rank", rank);
try
{
connection.Open();
if (Convert.ToInt32(command.ExecuteScalar()) > 0)
{
return true;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return false;
}
private void DeleteMovie(string rank)
{
string query = "DELETE FROM MovieList WHERE Rank= #Rank";
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
OleDbCommand command = new OleDbCommand(query);
command.Connection = connection;
command.Parameters.AddWithValue("#Rank", rank);
try
{
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Is it possible to use SQL command for login and update at the same time? I mean when the Login is done, I want to change logat in 1. Do I have to create a new if with OpenConnection()?
public bool IsLogin(string user, string pass) {
string query = $"SELECT * from utiliz WHERE username='{user}' AND password='{GetSha1(pass)}'";
string query_update = $"UPDATE utiliz SET logat='{1}' WHERE username='{user}'";
try
{
if (OpenConnection())
{
MySqlCommand cmd = new MySqlCommand(query, conn);
MySqlDataReader reader = cmd.ExecuteReader();
if (reader.Read())
{
reader.Close();
conn.Close();
return true;
}
else
{
reader.Close();
conn.Close();
return false;
}
}
else {
conn.Close();
return false;
}
}
catch (Exception ex) {
conn.Close();
return false;
}
}
EDITED
Guys, I have edited my code, following parameters procedure. Is it good what I did?
if (String.IsNullOrEmpty(textBox_pass_login.Text) && String.IsNullOrEmpty(textBox_usr_login.Text) || String.IsNullOrEmpty(textBox_usr_login.Text) || String.IsNullOrEmpty(textBox_pass_login.Text))
{
System.Windows.Forms.MessageBox.Show("Both fields (username,password) are required");
}
else
{
string user = textBox_usr_login.Text;
string password = textBox_pass_login.Text;
string encryptedpass = GetSha1(password);
try
{
using (var connection = conn)
{
string query = "SELECT * from utiliz WHERE username=#user AND password=#password";
using (var command = new MySqlCommand(query, conn))
{
command.Parameters.AddWithValue("#user", user);
command.Parameters.AddWithValue("#password", encryptedpass);
MySqlDataAdapter sda = new MySqlDataAdapter(command);
DataTable dt = new DataTable();
sda.Fill(dt);
conn.Open();
int i = command.ExecuteNonQuery();
conn.Close();
if (dt.Rows.Count > 0)
{
this.Hide();
var form2 = new Form1();
form2.Closed += (s, args) => this.Close();
form2.Show();
}
else
{
System.Windows.Forms.MessageBox.Show("Wrong credentials");
textBox_usr_login.Clear();
textBox_pass_login.Clear();
}
}
}
}
catch
{
System.Windows.Forms.MessageBox.Show("Wrong credentials");
textBox_usr_login.Clear();
textBox_pass_login.Clear();
}
}
There are some important points here. You must use Parameterized queries to improve the performence of your query on the database layer and avoid some problems such as sql injection. You also could use transactions to keep data integrity.
Check the sample bellow with comments (I didn't test this code, may not work properly on your environment):
public bool IsLogin(string user, string pass)
{
// prepare the queries with parameters with '#' and parameter name
const string query = "SELECT count(username) from utiliz WHERE username = #username AND password = #password";
const string query_update = "UPDATE utiliz SET logat = #logat WHERE username = #username";
// prepare the encrypted password
string encryptedPass = GetSha1(pass);
// use a result variable to use as the function result
bool result = false;
try
{
if (OpenConnection())
{
// start a transaction from the connection object
using (MySqlTransaction tran = conn.BeginTransaction())
{
try
{
int userFound = 0;
// prepare the MySqlCommand to use the query, connection and transaction.
using (MySqlCommand userCommand = new MySqlCommand(query, conn, tran))
{
userCommand.Parameters.AddWithValue("#username", user);
userCommand.Parameters.AddWithValue("#password", encryptedPass);
userFound = (int) userCommand.ExecuteScalar();
}
if (userFound > 0)
{
// prepare the MySqlCommand to use the query, connection and transaction to update data
using (MySqlCommand logatCommand = new MySqlCommand(query_update, conn, tran))
{
logatCommand.Parameters.AddWithValue("#logat", DateTime.Now);
logatCommand.Parameters.AddWithValue("#username", user);
logatCommand.ExecuteNonQuery();
}
}
// commit the transaction
tran.Commit();
result = true;
}
catch (Exception ex)
{
// perform some log with ex object.
tran.Rollback();
}
finally
{
conn.Close();
}
}
}
}
catch (Exception e)
{
// perform some log...
return false;
}
return result;
}
As recommended (and demonstrated) by Felipe Oriani, you should use parameterized queries.
Let me pinpoint, however, that you can do this with a single update query. The trick is to filter the update query on both user name and password:
UPDATE utiliz SET logat = #logat WHERE username = #username AND password = #password
You want to run the query with method ExecuteNonQuery, which returns the number of rows affected.
If credentials are valid, the where cause selects the relevant record and the update happens, returning 1 as the count of records affected. Else, no record is updated, and the method returns 0.
First of all, I will explain what happens as a process; when the admin logs in with username and the password, access will be granted and I have used a global variation which carries the username into every form. Hope this helps for my problem.
My login code is working fine:
try
{
SqlCommand selectCommand = new SqlCommand(" Select * from Login_users where USER_NAME=#USER_NAM and PASSWORD=#PASSWOR", conn);
selectCommand.Parameters.Add(new SqlParameter("USER_NAM", txtusername.Text.ToString()));
selectCommand.Parameters.Add(new SqlParameter("PASSWOR", txtpassword.Text.ToString()));
string UserType = null;
SqlDataReader reader = selectCommand.ExecuteReader();
bool rowfound = reader.HasRows;
if (rowfound)
{
while (reader.Read())
{
UserType = reader[2].ToString().Trim();
if (UserType == "ADMIN")
{
MessageBox.Show("Welcome ", "Admin Login", MessageBoxButtons.OK, MessageBoxIcon.Information);
Admin_StockControl frm = new Admin_StockControl();
frm.Show();
this.Hide();
}
else if (UserType == "STOCK_CON")
{
MessageBox.Show("Welcome ", "User Login", MessageBoxButtons.OK, MessageBoxIcon.Information);
Cashier frm = new Cashier();
frm.Show();
this.Hide();
}
}
}
else
{
MessageBox.Show(" Invalid User Or Password ", "Login ", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
reader.Close();
}
This is my Newuser table from the sql server database: with examples
ID | UserType | User_Name | Password | Create_Date
..................................................
1 ADMIN sam 123 5/5/17
2 STOCK_CON kage 456 6/5/17
---------------MY ISSUE-----------------
ADMIN will be able to create a new user from the MainMenu. By clicking the button tested as "Create_new user". This is the button which should be hidden for STOCK_CON. in other-wards, i need to invisible the a button named "bunifuFlatButton3" for "STOCK_CON" and make it visible for "ADMIN".
This is my code not functioning, I don't know how it works but I tried with this code:
private void Admin_Menu_Load(object sender, EventArgs e)
{
SqlCommand selectCommand = new SqlCommand(" Select * from New_User where User_Name=#USER_ID and Password=#PASS", conn);
bool rowfound = reader.HasRows;
string UserType = null;
SqlDataReader reader = selectCommand.ExecuteReader();
if (rowfound)
{
while (reader.Read())
{
UserType = reader["User_Type"].ToString().Trim();
if (UserType == "ADMIN")
{
bunifuFlatButton3.Visible = true;
}
else if (UserType == "STOCK_CON")
{
bunifuFlatButton3.Visible = false;
}
}
}
}
As Chris mentiond
You are calling reader.HasRows; prop before SqlDataReader reader = selectCommand.ExecuteReader(); just like the error says: Cannot use local variable 'reader' before it is declared
Try this
First you need to make sure your connection object (conn) is properly initilized
//intilize sql connection
SqlConnection conn=// method that creates your connection string
SqlCommand selectCommand = new SqlCommand(" Select * from New_User where
User_Name=#USER_ID and Password=#PASS", conn);
//add parametars if not added (i've added "sam" and "123" just for example, you should change this to strings that user types when login"
selectCommand.Parametars.AddWithValue("#USER_ID","sam");
selectCommand.Parametars.AddWithValue("#PASS","123");
string UserType = "";
//make sure to open connection before calling ExecuteReader()
conn.Open();
SqlDataReader reader = selectCommand.ExecuteReader();
if (reader.Read())
{
UserType = reader["User_Type"].ToString(); //you don't need Trim also
if (UserType == "ADMIN")
{
bunifuFlatButton3.Visible = true;
}
else if (UserType == "STOCK_CON")
{
bunifuFlatButton3.Visible = false;
}
}
You don't need while loop,Read() method returns false if there are no rows, see here examples of how to use SqlDataReader.
it might be because you are calling "bool rowfound = reader.HasRows;" and then SqlDataReader reader = selectCommand.ExecuteReader(); by the way you do not need if(rowfound) the while(reader.Read()) is enough.
and please do something like this :
cmd.Parameters.Add("#USER_ID", SqlDbType.Int).value = "(somthing)";
cmd.Parameters.Add("#PASS", SqlDbType.Int).value = "(somthing)";
using (SqlDataReader sdr = cmd.ExecuteReader())
{
UserType = sdr.GetString(Column Index); //<= try not to type hard string this will return the string value of the column index you enter
if (UserType == "Administrator")
{
bunifuFlatButton3.Visible = true;
}
else if (UserType == "StockController")
{
bunifuFlatButton3.Visible = false;
}
}
anyway try this and let me know if it worked as i dont really understand what part of your code is "not functioning"
I have to make automatic generate new AccountID on my load windows form app.
So for example when users start windows form "Add new Account" in textbox for "Account id" I have to show latest value from database. If i have two accounts in database on windows form in textbox value will be three.
My code perfectly work if i have at least one account in database, but when my database is empty i got exception.
This is my code:
public int GetLatestAccountID()
{
try
{
command.CommandText = "select Max(AccountID)as maxID from Account";
command.CommandType = CommandType.Text;
connection.Open();
OleDbDataReader reader= command.ExecuteReader();
if (reader.Read())
{
int valueID = Convert.ToInt32(reader["maxID"]);
return valueID + 1;
}
return 1;
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (connection!= null)
{
connection.Close();
}
}
}
Also I find answer on stackoverflow:
object aa = DBNull.Value;
int valueID = (aa as int?).GetValueOrDefault();
But this line of code works if my database is empty, but when I have one account in the database, it will always show on my windows form in account id textbox value one. I use Microsoft Access 2007 database.
I appreciate any help.
You may further simplify it like below,
Select isnull(max(accountID),0) as maxID from Account
I'm guessing you want:
public int GetLatestAccountID(string connectionString)
{
using(var dbConn = new OleDbConnection(connectionString))
{
dbConn.Open();
string query = "select Max(AccountID) from Account";
using(var dbCommand = new OleDbCommand(query, dbConn))
{
var value = dbCommand.ExecuteScalar();
if ((value != null) && (value != DBNull.Value))
return Convert.ToInt32(value) + 1;
return 1;
}
}
}
It looks like you're opening your database connection once and leaving it open during your entire program. Don't do that; that leads to race conditions and data corruption. .NET implements database connection pooling so you're not improving performance at all by leaving connections open.
You're also not telling us what you're using GetLatestAccountID for. If you're trying to use that as a primary key you are also going to run into problems with race conditions. If you want a primary key you should let the database create it and return the value after you've created the record.
public int GetLatestAccountID()
{
try
{
int accounts = 0;
command.CommandText = "select Max(AccountID)as maxID from Account";
command.CommandType = CommandType.Text;
connection.Open();
OleDbDataReader reader= command.ExecuteReader();
if (reader.Read())
{
accounts = Convert.ToInt32(reader["maxID"]) + 1;
}
return accounts;
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (connection!= null)
{
connection.Close();
}
}
}
Could you use SELECT COUNT(column_name) FROM table_name; to count number of accounts instead of selecting which one is the biggest?
In my Asp.Net application at the time of Login, I am first authenticating the User then getting some important information in session variables and it's working fine too.
However after sometime when session expires and I have to login again then it shows IndexOutOfRangeException in GetDetail() method. Here is my Login Button Code:
protected void btnLogin_Click(object sender, EventArgs e)
{
Session["UserName"] = txtUserName.Text;
string DefaultYear = GetDefaultFinYear();
if (DefaultYear != string.Empty)
{
DefaultYear = "connect" + DefaultYear;
Connections.Init(DefaultYear);
SqlDataAdapter adp = new SqlDataAdapter();
try
{
adp = new SqlDataAdapter("CheckLogin_sp", Connections.Connection[Session["UserName"].ToString()]);
adp.SelectCommand.Parameters.AddWithValue("#UserName", txtUserName.Text.Trim());
adp.SelectCommand.Parameters.AddWithValue("#Pwd", txtPassword.Text.Trim());
adp.SelectCommand.Parameters.AddWithValue("option", "Authenticate".Trim());
adp.SelectCommand.CommandType = CommandType.StoredProcedure;
if (Connections.Connection[Session["UserName"].ToString()].State == ConnectionState.Closed)
{
Connections.Connection[Session["UserName"].ToString()].Open();
}
SqlDataReader dr = adp.SelectCommand.ExecuteReader();
if (dr.HasRows)
{
Session["value"] = "admin";
dr.Close();
dr.Dispose();
GetDetails();
Response.Redirect("~/Masters/home.aspx", false);
}
else
{
MessageBox.Show("Invalid Password");
txtUserName.Text = string.Empty;
}
Connections.Connection[Session["UserName"].ToString()].Close();
adp.Dispose();
}
catch (Exception ex)
{
Response.Write(ex.ToString());
}
finally
{
Connections.Connection[Session["UserName"].ToString()].Close();
adp.Dispose();
}
}
else
{
MessageBox.Show("Invalid UserName");
}
}
GetDetails() Method:
private void GetDetails()
{
SqlCommand cmd = new SqlCommand();
SqlDataReader dr;
cmd.Connection = Connections.Connection[Session["UserName"].ToString()];
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "CheckLogin_sp";
cmd.Parameters.AddWithValue("option", "GetDetails".Trim());
cmd.Parameters.AddWithValue("UserName", txtUserName.Text);
cmd.Parameters.AddWithValue("Pwd", txtPassword.Text);
dr = cmd.ExecuteReader();
while (dr.Read())
{
Session["Name"] = dr["name"].ToString();
Session["CompanyName"] = dr["CompanyName"].ToString();
Session["UserId"] = dr["Id"].ToString();
Session["Center"] = dr["Center"].ToString();
Session["ClientCode"] = dr["ClientCode"].ToString();
Session["UserImage"] = dr["Image"].ToString();
Session["CurrentDatabase"] = dr["CurrentDatabase"].ToString();
Session["UserName"] = txtUserName.Text;
Connections.BillReport = dr["BillReport"].ToString();
Connections.DuesReport = dr["DuesReport"].ToString();
Connections.GeneralReport = dr["GeneralReport"].ToString();
Connections.PendingReport = dr["PendingReport"].ToString();
Connections.RadiologyReport = dr["RadiologyReport"].ToString();
Connections.HistoReport = dr["HistoReport"].ToString();
}
cmd.Parameters.Clear();
cmd.Dispose();
dr.Close();
}
Note:- When I check temporary files in my computer I found 6 GB temporary files in just 15 days. Is it because of heavy load of temporary files ? or something wrong in my Code ?
Can anyone tell me what I am doing wrong here ?
Try:
while (dr.Read() != null)
IndexOutOfRange exception is thrown when you attempt to access (Read/ Write) an element of an array with an index which is outside the bounds of the array
As per your problem, I guess you are trying to read or write some array elements which are outside of your array boundary.
for example:
It's error related when you are retriving index record which is not exist.
See if there's 5 elements in array, But when you are trying to retrieve record at index 6 then it will generate Exception of kind IndexOutOfRangeException.
See here HERE for more details.
You can try this code:
while (dr.Read() != null){
// code goes here.
}
OR
while(dr.Read() != ''){
// code goes here.
}
If not solved, you must be debug your program.