On my main form I have queried the user id on submission. Once I save the id to a variable how can I call it on another windows form in the same application?
This is what I have so far
private void btnLogin_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Data Source=.database.windows.net;Initial Catalog=userlogins;Persist Security Info=True;User ID=****;Password=****");
SqlDataAdapter sda = new SqlDataAdapter("Select ID from users where username='" + txtUsername.Text + "' and password='" + txtPassword.Text + "' ", con);
SqlCommand cmd = con.CreateCommand();
con.Open();
// save SQL ID to variable
cmd.CommandText = "Select Id from users where username = '" + txtUsername.Text + "'";
int sqlid = ((int)cmd.ExecuteScalar());
Any information would be appreciated, I really need the ID on multiple other pages!
If you are using the ExecuteScalar() method, it's important to remember that this will only return the contents of the first cell in your results, so it can generally help to use in conjunction with a TOP 1 statement.
Additionally, you should consider refactoring your code to use parameterization, which should help avoid nastiness like SQL Injection and will also help mitigate any syntax issues :
// Build your connection
using(var con = new SqlConnection("your-connection-string"))
{
// Build your query
var query = "SELECT TOP 1 ID FROM users WHERE username = #username AND password = #password";
// Build a command to execute your query
using(var cmd = new SqlCommand(con,query))
{
// Open your connection
con.Open();
// Add your parameters
cmd.Parameters.AddWithValue("#username", txtUsername.Text);
cmd.Parameters.AddWithValue("#password", txtPassword.Text);
// Get your ID
var sqlid = Convert.ToInt32(cmd.ExecuteScalar());
// Do something here
}
}
One way to do this is with events:
public class IdChangedEventArgs : EventArgs
{
int ChangedId {get;set;};
}
public delegate void IdChangedEventHandler(object sender, IdChangedEventArgs e);
public event IdChangedEventHandler IdChangedEvent;
private void btnLogin_Click(object sender, EventArgs e)
{
int sqlid = ((int)cmd.ExecuteScalar());
IdChangedEvent(this, new IdChangedEventArgs {ChangedId = sqlid;} );
}
In each of your interested forms, subscribe to the events. When handled, update your GUI however you want.
Related
When a user logs into the web site I am developing it the gets the session of the user by using this code:
protected void ButtonLogin_Click(object sender, EventArgs e)
{
Session["LoggedIn"] = UsernameTXT.Text;
....
Then I have a "Card" where it shows the total amount of "Online Users" which is set up in my Global.asax file:
void Application_Start(object sender, EventArgs e)
{
Application["OnlineUsers"] = 0;
}
void Session_Start(object sender, EventArgs e)
{
Application.Lock();
Application["OnlineUsers"] = (int)Application["OnlineUsers"] + 1;
Application.UnLock();
Session.Timeout = 8;
}
void Session_End(object sender, EventArgs e)
{
Application.Lock();
Application["OnlineUsers"] = (int)Application["OnlineUsers"] - 1;
Application.UnLock();
}
So to display the user that is logged in I have the following in my OnlineUsers.aspx.cs file:
protected void Page_Load(object sender, EventArgs e)
{
try
{
SqlConnection con = new SqlConnection(#"My Connection String");
con.Open();
SqlCommand cmd = new SqlCommand("SELECT first_name, last_name, email, user_name FROM tbl_um_user WHERE user_name = '"+ Session["username"].ToString() + "'", con);
cmd.CommandType = CommandType.Text;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds, "ss");
GridViewOnline.DataSource = ds.Tables["ss"];
GridViewOnline.DataBind();
}
.......
This works perfectly, but when another users logs in it then doesn't display that users information as per above.
I have had a look on various other post here on Stack Overflow and some suggest that you need to save the session in a database and retrieve from there? I might be wrong but does it not create a new session every time a user logs in? So then surely I should be able to display it? And how do I save the sessions in a database? (Sorry for all the questions :-) )
Any guidance, explanation or help will be greatly appreciated.
Thank you
SAVING TO DATABASE
Session["LoggedIn"] = UsernameTxt.Text;
string connectionString = System.Configuration.ConfigurationManager
.ConnectionStrings["CONN"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "UPDATE tbl_um_user SET IsLogged = #isLogged WHERE user_id_pk ='" + Session["LoggedIn"] + "'";
command.Parameters.AddWithValue("#isLogged", 1);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
SESSION END
<%# Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
Application["OnlineUsers"] = 0;
}
void Session_Start(object sender, EventArgs e)
{
Application.Lock();
Application["OnlineUsers"] = (int)Application["OnlineUsers"] + 1;
Application.UnLock();
Session.Timeout = 8;
}
void Session_End(object sender, EventArgs e)
{
Application.Lock();
Application["OnlineUsers"] = (int)Application["OnlineUsers"] - 1;
Application.UnLock();
string connectionString = System.Configuration.ConfigurationManager
.ConnectionStrings["CONN"].ConnectionString;
using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection(connectionString))
using (System.Data.SqlClient.SqlCommand command = connection.CreateCommand())
{
command.CommandText = "UPDATE tbl_um_user SET IsLogged = 0 WHERE user_id_pk ='" + Session["LoggedIn"] + "'";
command.Parameters.AddWithValue("#isLogged", 0);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
SqlCommand cmd = new SqlCommand("
SELECT first_name
, last_name
, email
, user_name
FROM tbl_um_user
WHERE user_name = '"+ Session["username"].ToString() + "'", con);
So the problem is in the last line:
WHERE user_name = '"+ Session["user","name"].ToString() + "'"
This will simply get the username of the user who is viewing the page (aka the session user).
If you want to resolve this you have to either store in memory the username of the users that log in everytime. You can use object cache. The logic is that when a user logs in you store his name in memory and then query with all those names.
WHERE user_name IN ("+ string.join(",", Your_Memory.Usernames)+ ")"
It's a simple list that stores the usernames.
Another solution would be for you to store them in your database with a simple flag you must create a column IsLogged BIT where you update it with 1 when the user logs in and when the user logs out make it a 0.
So you would query like this
WHERE IsLogged = 1
This eliminates the need for using in memory storing.
EDIT:
Session["LoggedIn"] = UsernameTxt.Text;
The error is because you try to compare your primary key which is an int with a string.
command.CommandText = "UPDATE tbl_um_user SET IsLogged = #isLogged WHERE user_id_pk ='" + Session["UserId"] + "'";
Here you have to get the userid. If you dont have the user id then search by username(if it is unique of course)
To update when session ends:
void Session_End(object sender, EventArgs e)
{
// your code
command.CommandText = "UPDATE tbl_um_user SET IsLogged = 0 WHERE user_id_pk ='" + Session["UserId"] + "'";
}
Just query the database on session_end just like you did on log in.
I am not getting, how to do insert and update of the data in C# WinForms on single button click.
private void save_Click(object sender, EventArgs e)
{
SqlConnection cn = new SqlConnection();
cn.ConnectionString = "data source=Sai;database=kaur; user id=sa;password=azxc;";
cn.Open();
string gen;
if (radioButton1.Checked == true)
gen = "Male";
else
gen = "Female";
string clas = null;
clas = comboBox1.Text;
string section = null;
section = comboBox2.Text;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "insert into studetail values('" + textBox1.Text + "','" + textBox2.Text + "','" + gen + "','" + textBox3.Text + "','" + clas + "','" + section + "')";
cmd.Connection = cn;
int n = cmd.ExecuteNonQuery();
if (n > 0)
MessageBox.Show(n + " Row Inserted.");
else
MessageBox.Show("Insertion failed.");
SqlDataAdapter da = new SqlDataAdapter("select * from studetail ", cn);
DataTable dt = new DataTable();
da.Fill(dt);
dataGridView1.DataSource = dt;
You can add a deletion before the insertion:
private void save_Click(object sender, EventArgs e)
{
DeletePerson(id); // add this
SqlConnection cn = new SqlConnection();
...
}
public void DeletePerson(int id)
{
using(SqlConnection connection = new SqlConnection(credentials))
{
connection.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = connection;
cmd.CommandText = "delete from studetail where someUniqeIdColumn = " + id;
cmd.ExecuteNonQuery();
}
}
Using responsible to dispose the connection.
Consider using Entity Framework or LINQ to SQL.
You are exposed to SQL injection.
First off the SQL query isn't quite right. It should look something like the following:
INSERT INTO studetail (columnName1, columnName2, ...columnNameN)
VALUES (value1, value2, ...valueN);
Where the column names are the columns where you want data to be inserted, and the values are the data you want inserted into said columns.
You should also be disposing the connection by wrapping the connection within a using statement.
using(var con = new SqlConnection(connectionString))
{
con.Open();
//rest of code that needs a connection here
}
Additionally, you need to be wary of SQL injection. I highly suggest reading this example from the MSDN website. It will give you an example of using an SQL Update and avoiding SQL injection with use of SqlCommand.Paramaters property.
You should also have a Primary Key in your database tables, if you don't already, so you can uniquely identify each record in a table.
To do an update and a save on the same button, you will need to check if a row already exists for the data that is being edited. This when a Primary comes in handy. You will want to check your database to see if a record already exists
SELECT 1 FROM studetail WHERE <Condition>
The WHERE condition will be the way you uniquely identify (a Primary Key) a row in your table. If the rows in the table are uniquely identified, the above SQL statement will return 1 if a value exists, which means you can UPDATE or 0 if no record exists, so you can INSERT
Good day!
I'm trying to figure out what error I'm having. This is the error:
And here is my code:
protected void accountGridView_RowEditing(object sender, GridViewEditEventArgs e)
{
accountGridView.EditIndex = e.NewEditIndex;
BindData();
}
protected void accountGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
int user_id = int.Parse(accountGridView.DataKeys[e.RowIndex].Value.ToString());
TextBox txtUsername = (TextBox)accountGridView.Rows[e.RowIndex].FindControl("txtUsername");
UpdateUser(user_id, txtUsername.Text);
accountGridView.EditIndex = -1;
BindData();
}
private void UpdateUser(int user_id, string username)
{
GlobalVars cn = new GlobalVars();
MySqlConnection connection = cn.connectDB();
connection.Open();
string query = "UPDATE user SET username = '" + username + " WHERE user_id = " + user_id + "";
MySqlCommand com = new MySqlCommand(query, connection);
com.ExecuteNonQuery();
connection.Close();
}
I can't get it to work. Am I missing something here?
Any help would be much appreciated.
The error message says that you have syntax errors in your query, so the other parts(connection) are working well as expected. Now consider the query:- if you debug the program and watch the query you can see that it may look like:
UPDATE user SET username = 'asd WHERE user_id= usr_123
So what is wrong here is, You ware missed a ' after asd, need to give a pair of ' to specify the user_id(if it is a string), so the query may look like this:
string query = "UPDATE user SET username = '" + username + "' WHERE user_id = '" + user_id + "'";
But i strongly recommend you to use Parameterized queries instead for this to avoid injection. The parameterised query will looks like :
string query = "UPDATE user SET username = #username WHERE user_id = #user_id";
MySqlCommand com = new MySqlCommand(query, connection);
com.Parameters.Add("#username", MySqlDbType.VarChar).Value = username;
com.Parameters.Add("#user_id", MySqlDbType.VarChar).Value = user_id;
// execute query here
I currently have a little app sends a lot of different MySQL Queries to the server. My idea was to wrap the connection, the query and the read to a function with only the actual query as a parameter.
Here is what I got:
public static MySqlDataReader mySqlRead(string cmdText)
{
string connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
MySqlConnection conn = new MySqlConnection(connString);
MySqlCommand command = conn.CreateCommand();
command.CommandText = cmdText;
try
{
conn.Open();
MySqlDataReader reader = command.ExecuteReader();
return reader;
}
catch (MySqlException)
{
throw;
}
}
I connect and send the query here:
private void btnLogin_Click(object sender, EventArgs e)
{
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
MySqlDataReader orRead = ORFunc.mySqlRead("SELECT * FROM orUsers WHERE username = '" + username + "' AND pass = '" + password + "'");
while (orRead.Read())
{
MessageBox.Show(orRead["id"].ToString());
}
}
Works like a charm... BUT, as you can see above, the connection is never closed. When I add the conn.Close() behind the .ExecuteReader() the reader is empty and everything after return is of course useless.
Maybe it's a stupid question but I'm rather new to C# so please be generous, any hint is appreciated.
cheers,
PrimuS
I had a similar problem in JAVA recently, but I think the same will work for you. Essentially, you can create a class that represents a "SqlCall" object (or something). The class would have accessible members including the connection and the results. The ctor for the class would take in your query text.
Then, all you would have to do is create a new instance of that class, run the query in a method in that class (which would set and/or return the results), GET the results, and then when you are done, call close() on your class (which would then have to be coded such that it closes the connection held internally).
Technically, a better way to do this is to EXTEND the connection class itself, but as you are new to C#, I will not go into the details of doing so.
As I was writing the code below, I realized I may have not actually answered your question. But there's no point in backing out now, so here's what I have:
public class SqlCall {
private static connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
private MySqlConnection conn;
private MySqlCommand command;
private MySqlDataReader reader;
public SqlCall(String query) {
conn = new MySqlConnection(connString);
command = conn.CreateCommand();
command.CommandText = query;
}
public MySqlDataReader execute() throws Exception {
conn.Open();
reader = command.ExecuteReader();
return reader;
}
public void close() {
reader.close();
conn.close();
}
}
Your login code would be:
private void btnLogin_Click(object sender, EventArgs e) {
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
SqlCall sqlcall = new SqlCall("SELECT * FROM orUsers WHERE username = '" + username + "' AND pass = '" + password + "'");
try {
MySqlDataReader orRead = sqlcall.execute();
while (orRead.Read())
{
MessageBox.Show(orRead["id"].ToString());
}
sqlcall.close();
} catch (Exception ex) {
// dostuff
}
}
The point is, unless you copy the data into a new datatable at the very beginning, you'll have to keep the connection open.
On a separate note, YOUR CODE IS PRONE TO SQL INJECTION. Don't know what that is? An example: if I said my username was ';DROP TABLE orUsers;--, then your entire user database would be gone. Look into stored procedures if you want a (very healthy) way around this.
You have difficulties because your idea works against the pattern expected by programs that connects to a database in NET Framework.
Usually, in this pattern you have a method that
INITIALIZE/OPEN/USE/CLOSE/DESTROY
the ADO.NET objects connected to the work required to extract or update data
Also your code has a serious problem called Sql Injection (see this famous explanation) because when you concatenate strings to form your command text you have no defense against a malicious user that try to attack your database
private void btnLogin_Click(object sender, EventArgs e)
{
string username = txtLogin.Text;
string password = ORFunc.GetMD5Hash(txtPassword.Text);
MySqlParameter p1 = new MySqlParameter("#uname", username);
MySqlParameter p2 = new MySqlParameter("#pass", pass);
string cmdText = "SELECT * FROM orUsers WHERE username = #uname AND pass = #pass"
DataTable dt = ORFunc.GetTable(cmdText, p1, p2);
foreach(DataRow r in dt.Rows)
{
Console.WriteLine(r["ID"].ToString());
}
}
public static DataTable GetTable(string cmdText, params MySqlParameter[] prms)
{
string connString = "server=" + ORVars.sqlServerAddr + ";port=" + ORVars.sqlServerPort + ";uid=" + ORVars.sqlServerUID + ";pwd=" + ORVars.sqlServerPass + ";database=" + ORVars.sqlServerDB + ";";
// This is the INITIALIZE part
using(MySqlConnection conn = new MySqlConnection(connString))
using(MySqlCommand command = new MySqlCommand(cmdText, conn))
{
// OPEN
conn.Open();
DataTable dt = new DataTable();
command.Parameters.AddRange(prms);
// USE
MySqlDataReader reader = command.ExecuteReader();
dt.Load(reader);
return dt;
} // The closing brace of the using statement is the CLOSE/DESTROY part of the pattern
}
Of course this is a generic example and in my real work I don't use very often these generic methods and prefer to write specialized data access code that return the base object needed to the upper layer of code
I have the following code in my btn_click event:
Sqlconnection con = new Sqlconnection("server=.;database=bss;user id=ab;pwd=ab");
con.open();
SqlCommand cmd = new Sqlcommand("select * from login where username='"
+ txt4name.Text + "' and pwd='" + txt4pwd.Text + "'", con);
SqlDataReader reader = cmd.execute Reader();
Where login is the table and username and pwd are its fields. After this code all the values are stored in the reader object. I want to store username and pwd in the separate variables.
How can I accomplish this?
In general, when accessing your DB, you should be using something similar to this instead to eliminate SQL injection vulnerabilities:
using (SqlCommand myCommand = new SqlCommand("SELECT * FROM USERS WHERE USERNAME=#username AND PASSWORD=HASHBYTES('SHA1', #password)", myConnection))
{
myCommand.Parameters.AddWithValue("#username", user);
myCommand.Parameters.AddWithValue("#password", pass);
myConnection.Open();
SqlDataReader myReader = myCommand.ExecuteReader())
...................
}
But more realistically to store credentials, you should be using something like the Membership system instead of rolling your own.
You're running a huge risk of sql injection with that. Use SQL Parameters for values into SqlCommands.
If you mean c# variables, and if you want to get them from db, just do this:
SqlDataReader reader = cmd.execute Reader();
if (reader.Read())
{
string username = reader["username"];
string pwd = reader["password"];
}
While you are at it, parameterize your query and prevent sql injection:
SqlCommand cmd = new Sqlcommand("select * from login where username=#username and pwd=#pwd", con);
cmd.Parameters.AddWithValue("#username", txt4name.Text);
cmd.Parameters.AddWithValue("#pwd", txt4pwd.Text);
Definitely heed the advice about SQL injection but here is the answer to your question:
String username;
String pwd;
int columnIndex = reader.GetOrdinal("username");
if (!dataReader.IsDBNull(columnIndex))
{
username = dataReader.GetString(columnIndex);
}
columnIndex = reader.GetOrdinal("pwd");
if (!dataReader.IsDBNull(columnIndex))
{
pwd = dataReader.GetString(columnIndex);
}
string userName = txt4name.Text;
string password = txt4pwd.Text;
Is that really what you want? Just to get that data into variables?
You really need to use parameterized SQL. There's an example here
Furthermore, your question doesn't really make sense; you want the username and password in seperate variables? they already are seperate in your example. If you are unable to assign them to strings I suggest following some tutorials.
Another approach is to load the reader results into a DataTable like so:
DataTable Result = new DataTable();
Result.Load(reader);
If your login table only contains two columns (userName and password) that are unique you end up with Result containing only one row with the information. You can then get the column values from each column:
string userName = Result.Rows[0].Field<string>("userName");
string password = Result.Rows[0].Field<string>("pwd");
private void but_login_Click(object sender, EventArgs e)
{
string cn = "Data Source=.;Initial Catalog=mvrdatabase;Integrated Security=True";
SqlConnection con = new SqlConnection(cn);
con.Open();
SqlCommand cmd = new SqlCommand("select count (*) from logintable where username ='" + txt_uname.Text + "'and password='" + txt_pass.Text + "'", con);
int i = Convert.ToInt32(cmd.ExecuteScalar());
con.Close();
if (i == 1)
{
Form2 f2 = new Form2();
MessageBox.Show("User login successfully........");
this.Hide();
f2.Show();
}
else
{
MessageBox.Show("INCORRECT USERID AND PASSWORD", "Error");
}
}
You can usually find basic usage examples on MSDN, like this one for SqlDataReader.