How do I display the data of the "current user"? - c#

I am a high school student who's still pretty much a beginner in C#.
I am making a library management system (for books) that includes a database (sql local database in visual studio(?)) for users. I have a form wherein users can view the data they have input in the registration form (userID, name, username, course, section). The only problem is that it only displays the data of the first account created. No matter how many other accounts I create, it still only ever displays the first one. How do I make it so that it shows the data of the "current" user/account logged in?
I've tried slightly changing the code by changing
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select * from [tbl_accounts]";
into
string select = "Select * from [tbl_accounts]";
SqlCommand cmd = new SqlCommand(select, conn);
Although, I think they're basically the same. I don't really know what to do since the other solutions I've found are much more complex.
This is the code that I am using right now:
try
{
SqlConnection conn = new SqlConnection(#"[connection string]");
conn.Open();
string select = "Select * from [tbl_accounts]";
SqlCommand cmd = new SqlCommand(select, conn);
SqlDataReader dr = cmd.ExecuteReader();
if(dr.Read())
{
materialLabel6.Text = dr["accountID"].ToString();
materialLabel7.Text = dr["username"].ToString();
materialLabel8.Text = dr["name"].ToString();
materialLabel9.Text = dr["strand"].ToString();
materialLabel10.Text = dr["section"].ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);}
}
The outcome that I would like to see is for example:
Users(table):
PersonA
PersonB
Currently Logged in: PersonB
[PERSONB'S DATA]
So it means that the form will only display the data of PersonB instead of PersonA's

For starters, if you need more than one row of data, you'll want to loop through all the rows in the data reader. Right now you're only getting the first row returned. This link should have the relevant information for that. However, ideally, you'd want to send a parameter from the UI (or whatever it is that you're using to fire off the call to the function) that denotes the user (an ID or any unique field in the Users table) and send that to the sql query's where clause so you only pull the record(s) that you need.
The query should probably look something like:
public void GetUserInfo(int userId) // though you might want to change the parameter to suit your needs. It's hard to tell without being able to see the schema
{
string select = string.Format("Select * from [tbl_accounts] where Id = {0}", userId.ToString()); // something along these lines
SqlCommand cmd = new SqlCommand(select, conn);
SqlDataReader dr = cmd.ExecuteReader();
if(dr.Read())
{
materialLabel6.Text = dr["accountID"].ToString();
materialLabel7.Text = dr["username"].ToString();
materialLabel8.Text = dr["name"].ToString();
materialLabel9.Text = dr["strand"].ToString();
materialLabel10.Text = dr["section"].ToString();
}
}
Edit: quick note, if you adjust your query so it pulls one record based off of a parameter, you shouldn't need to do the looping.
Another quick edit: I broke up the code so it's a little more readable. This is more of an 'ideal implementation,' and enforces some better practices for code. (I know it's a high school project, but it's best to get used to breaking up code so it's more generic early on imo. This is mostly for maintainability. On larger projects keeping everything so closely coupled together is hard to manage.)
public User GetUserInfo(int userId) // though you might want to change the parameter to suit your needs. It's hard to tell without being able to see the schema for the user table
{
SqlConnection conn = new SqlConnection(#"[connection string]");
conn.Open();
string select = string.Format("Select * from [tbl_accounts] where Id = {0}", userId.ToString()); // something along these lines
SqlCommand cmd = new SqlCommand(select, conn);
SqlDataReader dr = cmd.ExecuteReader();
User user = new User();
if(dr.Read())
{
user.AccountId = dr["accountID"].ToString();
user.UserName = dr["username"].ToString();
user.Name = dr["name"].ToString();
user.Strand = dr["strand"].ToString();
user.Section = dr["section"].ToString();
}
return user;
}
public void SetValues(User user)
{
materialLabel6.Text = user.AccountId;
materialLabel7.Text = user.UserName;
materialLabel8.Text = user.Name;
materialLabel9.Text = user.Strand;
materialLabel10.Text = user.Section;
}
public class User
{
string AccountId { get; set; }
string UserName { get; set; }
string Name { get; set; }
string Strand { get; set; }
string Section { get; set; }
}

Related

WHERE Name='{NameInput.Text}' AND Password='{GetHashString(PasswordInput.Text)} not working

I'm trying to get my LoginButton to work, it isn't really doing what I want it to do.
I already have a RegisterButton which works perfectly and creates the account without any problems, but when trying to do my LoginButton it connects to the database but doesn't really check if the account exists using selectQuery and it should change WarningLabel.Text to "Wrong Name or Password". it does go through the first try and changes the WarningLabel.Text to "Welcome " + NameInput.Text;
private void LoginButton_Click(object sender, System.EventArgs e)
{
string selectQuery = $"SELECT * FROM bank.user WHERE Name='{NameInput.Text}' AND Password='{GetHashString(PasswordInput.Text)}';";
MySqlCommand cmd;
connection.Open();
cmd = new MySqlCommand(selectQuery, connection);
try
{
cmd.ExecuteNonQuery();
WarningLabel.Text = "Welcome " + NameInput.Text;
} catch
{
WarningLabel.Text = "Wrong Name or Password";
}
connection.Close();
}
Best Regards - Nebula.exe
The ExecuteNonQuery is not intented to be used with SQL statements that return data, you should use ExecuteReader or ExecuteScalar, you can check the MySqlCommand.ExecuteReader documentation
Warning: Your code does have a SQL Injection vulnerability in this part of the SQL statement Name='{NameInput.Text}' Check this SQL Injection explanation
Usage example (from the documentation, slightly modified):
using (MySqlConnection myConnection = new MySqlConnection(connStr))
{
using (MySqlCommand myCommand = new MySqlCommand(mySelectQuery, myConnection))
{
myConnection.Open();
MySqlDataReader myReader = myCommand.ExecuteReader();
while (myReader.Read())
{
Console.WriteLine(myReader.GetString(0));
}
}
}
You should check if there are records returned. cmd.ExecuteNonQuery(); won't tell you if records are returned because it will just execute the query. You should use ExecuteScalar or a MySQL Data Reader ExecuteReader and track the results.
Note : Your code is prone to SQL Injections, you might want to use Parameters in your query like #name and #password.
Your Query goes something like this.
string selectQuery = $"SELECT IFNULL(COUNT(*),0) FROM bank.user WHERE Name=#name AND Password=#password;";
Then use parameters
cmd.parameters.AddWithValue(#name, NameInput.Text);
cmd.parameters.AddWithValue(#password, GetHashString(PasswordInput.Text));
Then verify if the query returns result
If cmd.ExecuteScalar() > 0
//If count is > 0 then Welcome
//Else Wrong username or password
End If
Your life, made easy:
private void LoginButton_Click(object sender, System.EventArgs e)
{
var cmd = "SELECT * FROM bank.user WHERE Name=#name AND Password=#pw";
using var da = new MySqlDataAdapter(cmd, connection);
da.SelectCommand.Parameters.AddWithValue("#name", NameInput.Text);
da.SelectCommand.Parameters.AddWithValue("#pw",GetHashString(PasswordInput.Text));
var dt = new DataTable();
da.Fill(dt);
if(dt.Rows.Count == 0)
WarningLabel.Text = "Wrong Name or Password";
else
WarningLabel.Text = $"Welcome {dt.Rows[0]["FullName"]}, your last login was at {dt.Rows[0]["LastLoginDate"]}";
}
Your life, made easier (with Dapper):
class User{
public string Name {get;set;} //username e.g. fluffybunny666
public string FullName {get;set;} //like John Smith
public string Password {get;set;} //hashed
public DateTime LastLoginDate {get;set;}
}
//or you could use a record for less finger wear
record User(string Name, string FullName, string Password, DateTime LastLoginDate);
...
using var c = new MySqlConnection(connection):
var u = await c.QuerySingleOrDefaultAsync(
"SELECT * FROM bank.user WHERE Name=#N AND Password=#P",
new { N = NameInput.Text, P = GetHashString(PasswordInput.Text)}
);
if(u == default)
WarningLabel.Text = "Wrong Name or Password";
else
WarningLabel.Text = $"Welcome {u.FullName}, your last login was at u.LastLoginDate";

How to send properties with SQL in C#

I have two classes, first name is class 1 to collect your name and family addition to your car. This came from another class that name is car.
This class (car) has two properties, actually I won't get information directly.
For these classes we have two tables as well - first table has relation with class 1, name is qqq and car connected with car.
What's the problem?
In qqq table I have column id_car. When the customer registers himself, his car id should be stored into the qqq table.
I don't know how pass properties with SQL command
Server code:
public class Class1
{
public int id { get; set; }
public string name { get; set; }
public string family { get; set; }
public car car_id { get; set; }
}
public class car
{
public int id { get; set; }
public String name { get; set; }
public String color { get; set; }
}
Client-side code:
SqlCommand sqlCommand = new SqlCommand();
sqlCommand.Connection = sqlcon;
sqlCommand.CommandText = "insert into cars (name , color) values('BMW','gray');";
sqlCommand.ExecuteNonQuery();
SqlCommand sqlCommand1 = new SqlCommand();
sqlCommand1.Connection = sqlcon;
sqlCommand1.CommandText = "insert into qqq (name, family, id_car) values (#name, #family, #car);";
sqlCommand1.Parameters.AddWithValue("#name", textBox1.Text);
sqlCommand1.Parameters.AddWithValue("#family", textBox2.Text);
sqlCommand1.Parameters.AddWithValue("#car", "***MAIN PROBLEM***");
sqlCommand1.ExecuteNonQuery();
The answer is in the code below. There are also several things here that should be improved, which I will call out via the comments:
//You can put several statements in one sql string.
string sql = "
declare #car int;
insert into cars (name , color) values('BMW','gray');
set #car = scope_identity();
insert into qqq (name, family ,id_car) values (#name,#family,#car);";
// Create a new connection object for each call to the database. Really.
// Read this for more info why: https://softwareengineering.stackexchange.com/q/142065/8057
using (var sqlcon = new SqlConnection("connection string here"))
using (var command = new SqlCommand(sql, sqlcon))
{
//AddWithValue can cause certain serious performance problems
// Instead, be specific about the database type and length for the target column.
// I have to guess here, but you can find this info in your database
command.Parameters.Add("#name", SqlDbType.NVarChar, 50).Value = textBox1.Text;
command.Parameters.Add("#family", SqlDbtype.NVarChar, 120).Value = textBox2.Text;
sqlcon.Open();
command.ExecuteNonQuery();
} // The connection will be closed and disposed here, even if an exception is thrown.
// Your original code would have left the connection open if there was an exception.
If you want to be really careful, you'll also add a transaction to that SQL. This way if the second part fails the first part can be rolled back and you don't end up accidentally only doing part of the work.
If you still want the new id_car value for later use in your application, you can further add a select #car; to the end of the SQL string and change ExecuteNonQuery() to ExecuteScalar() to get the value back.
First at all, you can get the last ID if it is a Identity ID (AUTO_INCREMENT) after insert to the table Car. Then past this ID to the qqq table.
Example:
// for MySQL
sqlCommand.CommandText = "INSERT INTO CARS (name , color) VALUES('BMW','gray') OUTPUT INSERTED.ID VALUES(#UserId, #GameId)";
Int32 newId = (Int32) sqlCommand.ExecuteScalar();
// for SQL Server
sqlCommand.CommandText = "INSERT INTO CARS (name , color) VALUES('BMW','gray') VALUES(#UserId, #GameId); SELECT SCOPE_IDENTITY();";
int primaryKey = Convert.ToInt32(sqlCommand.ExecuteScalar());
SqlCommand sqlCommand1 = new SqlCommand();
sqlCommand1.Connection = sqlcon;
sqlCommand1.CommandText = "insert into qqq (name , family ,id_car) values (#name,#family,#car);";
sqlCommand1.Parameters.AddWithValue("#name", textBox1.Text);
sqlCommand1.Parameters.AddWithValue("#family", textBox2.Text);
sqlCommand1.Parameters.AddWithValue("#car", newId); // mysql
sqlCommand1.Parameters.AddWithValue("#car", primaryKey); // sql server

Update Set command works in Access but not in Visual Studio with #parameters

I have been working on a personal project for the company I work for to control stock levels in order to practice my c#.
I want my application to search through tblJuiceStock, find a matching FlavourID to what the user is inputting and update the stock of that record through an UPDATE SET query.
public void InsertJuiceStockWithCheck()
{
using (OleDbConnection conn = new OleDbConnection())
{
conn.ConnectionString = ConnectionString;
conn.Open();
string tblJuiceStockCheck = "SELECT FlavourID, Quantity FROM tblJuiceStock";
OleDbCommand cmdCheck = new OleDbCommand(tblJuiceStockCheck, conn);
OleDbDataAdapter daCheck = new OleDbDataAdapter(cmdCheck);
DataTable dtCheck = new DataTable();
daCheck.Fill(dtCheck);
foreach (DataRow row in dtCheck.Rows)
{
if ((int)row["FlavourID"] == fID)
{
int currentQty = (int)row["Quantity"];
int updatedQty = currentQty + qty;
string tblJuiceStockExisting = #"UPDATE tblJuiceStock
SET Quantity = #newquantity
WHERE FlavourID = #flavourID";
OleDbCommand cmdJuiceStockExisting = new OleDbCommand(tblJuiceStockExisting, conn);
cmdJuiceStockExisting.Parameters.AddWithValue("#flavourID", fID);
cmdJuiceStockExisting.Parameters.AddWithValue("#newquantity", updatedQty);
cmdJuiceStockExisting.ExecuteNonQuery();
matchFound = true;
break;
}
}
if (!matchFound)
{
string tblJuiceStockNew = "INSERT INTO tblJuiceStock (FlavourID, Quantity, MinStockPOS) VALUES (#fID, #quantity, #minstock)";
OleDbCommand cmdJuiceStockNew = new OleDbCommand(tblJuiceStockNew, conn);
cmdJuiceStockNew.Parameters.AddWithValue("#fID", fID);
cmdJuiceStockNew.Parameters.AddWithValue("#quantity", qty);
cmdJuiceStockNew.Parameters.AddWithValue("#minstock", amt);
cmdJuiceStockNew.ExecuteNonQuery();
}
}
}
Please note: this query works fine in Access when I replace parameters with the same values. Also, using breakpoints I identified that the parameters have the correct values set to them, the variables assigned to them are obtained within another method, all methods are called in the submit button event.
However, the Quantity value in TblJuiceStock remains the same.
My tblJuiceStock table
After some time of messing about the answer was simple.
OLEDB does work with named parameters but you have to declare them, if you don't declare them they use the parameters positioning to match them up.
My problem was that in my query string I had #newquantity first and #flavourID second, whereas when adding my parameters I added #flavourID first and #newquantity second.

How to delete data from combobox if it's present in the database table

I have a situation where I have to assign room numbers to the customers and delete the assigned room numbers from the list.
I think I will be done by searching the table of the database. And if the program finds any assigned room number in the database, then it deletes it from the combobox.
I am using this code:
con.Open();
string selectSQL = "SELECT Room_Number FROM Reservation WHERE Reservation_ID > 0";
SqlCommand cmd = new SqlCommand(selectSQL, con);
SqlDataReader rd = cmd.ExecuteReader();
while (rd.Read())
{
string RoomNumber = rd.GetString(0);
foreach (string NumberOfRoom in RoomNumber)
{
if (NumberOfRoom == cbRoomNumber.Text)
{
cbRoomNumber.
}
}
}
rd.Close();
con.Close();
But I don't know what to do next.
Please any guidance will be helpful.
Don't mix DB querying logic with whatever happens outside. What you really need is some kind of RoomRepository such that you could do roomRepo.IsFree(any_parameter_goes_here). So:
if (roomRepo.IsFree(...)) { } gives you a nice way to alter execution at the given point without hardcoding SQL into method implementation.
Not quite sure my answer is what you were seeking for, but that's certainly a good starting point toward much more clean solution.
Thanks, Everybody. I made the Logic.
Here it is.
con.Open();
string selectSQLR = "SELECT Room_Number FROM Reservation where Reservation_ID > 0";
SqlCommand cmdR = new SqlCommand(selectSQLR, con);
SqlDataReader rdR;
rdR = cmdR.ExecuteReader();
while (rdR.Read())
{
string RoomNumber = rdR.GetString(0);
cbRoomNumber.Items.Remove(RoomNumber);
}
rdR.Close();
con.Close();
I think you meant to do this
if (NumberOfRoom == cbRoomNumber.Text)
{
cbRoomNumber.Items.Remove(NumberOfRoom)
}

validation of data with sql and c#

i've been struggling to understand how to validate data i entered in an input in an .aspx webform,
say username and password, i've tried many things, tried reading about it and looking for solutions but all of them are really messy with a lot of things i don't really need.
It is for a school project in my school and i already set up a working database, and i already made a register page, that works and it submits it to the database.
Our teachers supplied us with a DalAccess file, that is stored in the App_Data folder in my project.
This is the code inside of it:
public class DalAccess
{
private OleDbConnection conn;
private OleDbCommand command;
private OleDbDataAdapter adapter;
public DalAccess(string strQuery)
{
string ConnectionString = string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\Database.accdb");
conn = new OleDbConnection(ConnectionString);
command = new OleDbCommand(strQuery, conn);
adapter = new OleDbDataAdapter(command);
}
public DataSet GetDataSet(string strSql)
{
DataSet ds = new DataSet();
command.CommandText = strSql;
adapter.SelectCommand = command;
adapter.Fill(ds);
return ds;
}
public int InsertUpdateDelete(string strSql)
{
int rowsAffected;
this.conn.Open();
OleDbCommand cmd = new OleDbCommand(strSql, conn);
rowsAffected = cmd.ExecuteNonQuery();
conn.Close();
return rowsAffected;
}
}
Note: i am a complete beginner and have no idea what does anything in that code means.
So, i wrote these lines of code in the aspx.cs page behind
{
public DataSet ds ;
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack) {
string loginid = Request.Form["loginid"];
string loginpw = Request.Form["loginpw"];
string sqlS = "Select IDD,Pass from UserInfo where IDD = '"+ loginid + "'";
DalAccess dal = new DalAccess(sqlS);
ds = dal.GetDataSet(sqlS);
}
}
}
And if i wrote it correctly i selected the two tabs of the row that the value of IDD(ID of the user) in the table is loginid.
Problem is, i can't figure out how to take that data i selected and compare it to the things entered into the inputs and to check if they match.
I'd greatly appreciate if someone were to go as far as explain to me what everything does, since my teacher hasn't got a lot of time to give to all the students, but an example and a simple explanation will work for me too.
Important note!: I know if i make it parameterized it is safe against sql injection, which i did not do, but this part of the project is not for the purpose of security, which we will have a part for it too, and we will learn.
Thanks in advance.
when water rises above the level of the noses, only those will survive, who know how to swim, isn’t it?
Technically we will go for stored procedure to validate the login[as best practices].In the link the its very clear that you can do it with minimal coding.
How to validate login and pass userID
Updated:
ok, if we want to do it in your way.
In the code behind inside the method
private void ValidateLogin()
{
string uname = "Hsakarp";//I have hard-coded the value to make it simple
string pwd = "12345";
string sqlS = "Select UserName,Password from Login where UserName = '" + uname + "' and Password = " + pwd;
DalAccess dal = new DalAccess();
DataSet ds = dal.GetDataSet(sqlS); //GetDataset is gonna return the ds
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
if (ds.Tables[0].Rows[i]["UserName"].ToString().Trim() == uname && ds.Tables[0].Rows[i]["Password"].ToString().Trim() == pwd)
//Check whether the username and password exists.
Label1.Text = "Login Successfull";
else
Label1.Text = "Login failed";
}
}

Categories