Rework using parameterized queries C# - c#

There is a lot of tutorials regarding parameterized queries but most of them involve using SqlCommand, the only thing my code accepts is SqlDataAdapter for my SQL command, anytime I try to instantiate it as a SqlCommand I get errors.
TL;DR
I either need guidance on how to rework this using parameterized queries or I need to know why my SqlDataAdapter line doesn't work as an SqlCommand line.
private void btnLogin_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Jake\Documents\Data.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True;");
SqlDataAdapter sda = new SqlDataAdapter("Select Count(*) From Login Where Username = '" + txtUsername.Text + "' and Password = '" + txtPassword.Text + "'", con);
DataTable dt = new DataTable();
sda.Fill(dt);
if (dt.Rows[0][0].ToString() == "1")
{
this.Hide();
MessageBox.Show("LOGIN!");
}
else
{
MessageBox.Show("FAILED!");
}
}

You can use:
using (SqlDataAdapter sqlDA = new SqlDataAdapter("Select * from user where username = #username and password = #pass", sqlConnect))
{
sqlDA.SelectCommand.CommandType = CommandType.Text;
sqlDA.SelectCommand.Parameters.Add("#username", SqlDbType.Varchar).Value = username;
sqlDA.SelectCommand.Parameters.Add("#pass", SqlDbType.Varchar).Value = password;
sqlDA.Fill(dataTableVariable);
return dataTableVariable;
}
For your password remember to use a hash algorithm
This code is not tested. If you want the best performance you can explore execute scalar.

You can use Parameters.AddWithValue in SqlDataAdapter
sda.SelectCommand.Parameters.AddWithValue("#ParamName",value);
Check this: c# Using Parameters.AddWithValue in SqlDataAdapter

Try using parametrize query, it will avoids errors and sql injection
Once you have the reader you can use HasRow() to check if a record is returned
string conString = "xxxxxxxxxxxxxxxxxxxxxxxx";
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
using (var cmd = new SqlCommand(
"SELECT * FROM Login Where Username=#Username AND Password=#Password",
con))
{
cmd.Parameters.AddWithValue("#Username", txtUsername.Text);
cmd.Parameters.AddWithValue("#Password", txtPassword.Text);
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRow())
{
if(reader.Read())
{
var username = reader["Username"].ToString();
}
}
else
{
//User does not exists
}
}
}
}
You will need to import some library:
using System;
using System.Data;
using System.Data.SqlClient;

Related

How to record count from ASP.NET using stored procedure?

I am trying to output the number of depositors which has a total of 5 but when I run the program it outputs only 1. I used stored procedure for this matter. I think something is missing when in the codes below and I don't know. I tried my best to search on the internet.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
CountAllUsers();
}
}
protected void CountAllUsers()
{
using (MySqlConnection mycon = new MySqlConnection(constring))
{
mycon.Open();
MySqlCommand cmd = new MySqlCommand("countallusers", mycon);
cmd.CommandType = CommandType.StoredProcedure;
MySqlDataAdapter adx = new MySqlDataAdapter(cmd);
DataSet ds= new DataSet();
adx.Fill(ds);
mycon.Close();
lblDepositors.Text = ds.Tables[0].Rows.Count.ToString();
}
You can use ExecuteScalar to do the query for counting the number of records. Replace TABLE_NAME with your table.
FYI, you don't have to call mycon.Close();, as you apply using statement, when it ends, it will dispose the connection automatically.
Updated:
Added using block for MySqlCommand for Disposable best practice as suggested by #Dai.
protected void CountAllUsers()
{
using (MySqlConnection mycon = new MySqlConnection(constring))
{
using (MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM TABLE_NAME", mycon))
{
cmd.CommandType = CommandType.Text;
mycon.Open();
var count = Convert.ToInt32(cmd.ExecuteScalar());
lblDepositors.Text = count.ToString();
}
}
}
MySqlCommand.ExecuteScalar Method
ExecuteScalar method to retrieve a single value (for example, an aggregate value) from a database.
I already solved. Thanks!
protected void CountAllUsers()
{
using (MySqlConnection mycon = new MySqlConnection(constring))
{
mycon.Open();
MySqlCommand cmd = new MySqlCommand("SELECT COUNT(id) as count from depositors_tbl", mycon);
MySqlDataAdapter ada = new MySqlDataAdapter();
DataSet dt = new DataSet();
ada.SelectCommand = cmd;
ada.Fill(dt);
mycon.Close();
lblDepositors.Text = dt.Tables[0].Rows[0]["count"].ToString();
}
}

Database update error with SQL Server 2012 and C#

I am trying to update my data in a SQL Server database through C#. I am getting updated. But the problem is the data is updated twice.
For example I have 10 (int) in my balance and if I add another 10, it turns to 30.
Any help would be appreciated.
Here is my code:
protected void LoginClick(object sender, EventArgs e)
{
DataTable dr = new DataTable();
string email = txtEmail.Text;
SqlConnection con = new SqlConnection(Ws.Con);
con.Open();
int s = Convert.ToInt32(add.Text);
SqlCommand cmd = new SqlCommand("Update [Order] set Balance=Balance+'" + s + "',Card='" + card.Text + "' where email=#email ", con);
cmd.Parameters.AddWithValue("email", email);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt = new DataTable();
sda.Fill(dt);
int i = cmd.ExecuteNonQuery();
con.Close();
}
I would like to rectify few mistakes in your code,
DataTable is not needed to execute the update query, ExecuteNonQuery will do the job
The adapter.Fill and ExecuteNonQuery do the same job here and that's why your updates happening twice
Make use of parameterization while dealing with user inputs to avoid exceptions
For parsing integers use int.TryParse instead for Convert.ToInt32
I think the following code would help you to do the same function in a smarter way:
int currentBalance = 0;
if(int.TryParse(txtAdd.Text, out currentBalance))
{
string querSql = "Update [Order] set Balance = Balance + #balance," +
" Card = #card where email = #email"
using (SqlConnection dbConn = new SqlConnection("connectionString here"))
{
dbConn.Open();
using (SqlCommand sqlCommand = new SqlCommand(querySql, dbConn))
{
sqlCommand.Parameters.Add("#balance", SqlDbType.int).value = currentBalance;
sqlCommand.Parameters.Add("#card", SqlDbType.VarChar).value = card.Text;
sqlCommand.Parameters.Add("#email", SqlDbType.VarChar).value = email;
sqlCommand.ExecuteNonQuery();
}
}
}
Please note: YOu are parsing the balance as an integer value, so I assume the column Balance is an integer field in the database, if not make use of corresponding datatype for the parameter #balance also update the parsing technique
As per the documentation:
SqlDataAdapter(SqlCommand)
Initializes a new instance of the SqlDataAdapter class with the specified SqlCommand as the SelectCommand property.
What is going wrong in your code?
Actually you are passing SqlDataAdapter your update query as the Select command. So now when you will use this instance of SqlDataAdapter to Fill your datatable then actually you are executing your Update command. Look at the following code along with comments to see what is going wrong:
DataTable dr = new DataTable();
string email = txtEmail.Text;
SqlConnection con = new SqlConnection(Ws.Con);
con.Open();
int s = Convert.ToInt32(add.Text);
SqlCommand cmd = new SqlCommand("Update [Order] set Balance=Balance+'" + s + "',Card='" + card.Text + "' where email=#email ", con);
cmd.Parameters.AddWithValue("email", email);
SqlDataAdapter sda = new SqlDataAdapter(cmd);//The Select command for SqlDataAdapter
//is actually now the update command specified by cmd instnace of SqlCommand
DataTable dt = new DataTable();
sda.Fill(dt);//here SqlDataAdapter will execute it's Select command which is actually set
//to an update statement so your record will be updated
int i = cmd.ExecuteNonQuery();//and here again the update command is being executed now
//directly using the SqlCommand cmd instance and thus your record gets updated twice
con.Close();
Fixed Code:
DataTable dr = new DataTable();
string email = txtEmail.Text;
SqlConnection con = new SqlConnection(Ws.Con);
con.Open();
int s = Convert.ToInt32(add.Text);
SqlCommand cmd = new SqlCommand("Update [Order] set Balance=Balance+'" + s + "',Card='" + card.Text + "' where email=#email ", con);
cmd.Parameters.AddWithValue("email", email);
//Create a new SqlComamnd
SqlCommand selectCommand = new SqlCommand("Select * from [Order]");
//Put the newly created instance as SelectCommand for your SqlDataAdapter
SqlDataAdapter sda = new SqlDataAdapter(selectCommand);
DataTable dt = new DataTable();
sda.Fill(dt);
int i = cmd.ExecuteNonQuery();
con.Close();
Hope this help and do have a look at the documentation for better understanding of the SqlDataAdapter and DataTable. Thanks.

Invalid user credentials in MySQL parameterized query

It shows invalid user credentials even though I inputted the right one. I don't know if I made the parameters wrong or if my query is wrong. I want to learn about parameterized queries but I don't know what I'm doing wrong here.
con.OpenConnection();
using (con.connection)
{
String query = "SELECT * FROM tblUser WHERE Username = #Username and Password = #Password";
try
{
MySqlCommand cmd = new MySqlCommand(query, con.connection);
cmd.Parameters.Add("#Username", MySqlDbType.VarChar).Value = txtUsername.Text;
cmd.Parameters.Add("#Password", MySqlDbType.VarChar).Value = txtPassword.Text;
cmd.ExecuteNonQuery();
DataTable dt = new DataTable();
MySqlDataAdapter da = new MySqlDataAdapter(cmd);
da.Fill(dt);
i = Convert.ToInt32(dt.Rows.Count.ToString());
if (i == 0)
{
MessageBox.Show("Invalid user credentials.");
}
else
{
//Do stuff
}
}
catch (MySqlException mse)
{
MessageBox.Show(mse.Message);
}
finally
{
con.CloseConnection();
}
Not sure why it is not working but if you use AddWithValue, it will work. Something like this
cmd.Parameters.AddWithValue("#Username", txtUsername.Text);
cmd.Parameters.AddWithValue("#Password", txtPassword.Text);
Change your code so that it's calls a method, when you click on a Button, pass the Username and Password variable into this Method. Create a AutoProperty for UserName and Password at the Class Level
private DataTable PopulateSomeDatatSet(DataSet aDataset, string UserName, string Password)
{
var query = "SELECT * FROM tblUser WHERE Username = #Username and Password = #Password";
MySqlDataAdapter sda;
using (SqlConnection connStr = new SqlConnection(ConnString)) //replace with your ConnectionString Variable
{
using (MySqlCommand cmd = new MySqlCommand(query, connStr))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#Username", MySqlDbType.VarChar).Value = UserName;
cmd.Parameters.Add("#Password", MySqlDbType.VarChar).Value = Password;
sda = new MySqlDataAdapter(cmd);
new MySqlDataAdapter(cmd).Fill(aDataset);
}
}
((IDisposable)sda).Dispose();
return aDataset.Tables[0];
}

How to validate Password and Username for website in c#

I have a simple login website, which is my first website project in Visual Studio 2015. I have successfully created a SQL database which contains user information like Username, Password, Email and Country, and I have also successfully created a user registration page where a new user can input there details and these details will be added to the database. This all works fine.
but I have hit a roadblock while attempting to validate the Username and Password against the stored values in the row containing the User data in the SQLdatabase to give the user access to the member only pages.
Heres my code snippet for when the user click the login button.
SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MembersConnectionString"].ConnectionString);
con.Open();
string checkUser = "SELECT * FROM Members where Username= '" + TextBoxSignUser.Text + "' and Password= '" + TextBoxSignPass.Text + "'";
SqlCommand cmd = new SqlCommand(checkUser, con);
cmd.ExecuteNonQuery();
con.Close();
I know what I need to do is probably something like this pseudocode below, but I am unsure how to go about validating this information against stored values in the database.
if ("Username" and "Password" == the value of Username and Password TextBox.Text)
{
Response.Write("Sign in successful");
Response.Redirect("MemberTestPage.aspx");
}
else
{
Response.Write("Details incorrect, Please try again")
}
Fill the data-table using data adapter one you get the data into a data-table you can get the return values of the query and match the parameters
DataTable Dt = new Datatable();
SqlDataAdapter sda = new SqlDataAdapter(cmd);
sda.Fill(dt);
if (dt.rows.count > 0 )
{
//MATCH FOUND
}
You can use like..
string query= "SELECT * FROM Members where Username= 'usr' and Password= 'pwd'";
SqlCommand cmd = new SqlCommand(query, con);
MySqlDataAdapter objda = new MySqlDataAdapter(cmd);
DataSet objDs = new DataSet();
objda.Fill(objDs);
if(objDs.Tables[0].Rows.Count>0)
{
Response.Write("Sign in successful");
Response.Redirect("MemberTestPage.aspx");
}
You could do as following without using Datasets,
var con = new SqlConnection("your connection string goes here");
SqlCommand cmd = new SqlCommand("SELECT * FROM Members where Username= 'usr' and Password= 'pwd'", con);
bool result = false;
cmd.Connection.Open();
using (cmd.Connection)
{
SqlDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
result = true;
}
if (result == true)
// Login successful
else
// Login failed
string query = string.Format("SELECT TOP 1 * FROM [Table] WHERE Username = '{0}' and Password = '{1}'", txtUsername.Text, txtPassword.Text);
command = new OleDbCommand(query, con);
var reader = command.ExecuteReader();
if (reader.HasRows)
{
//successfully login
}
else
//error message
I think first of all it is better to use ADO.NET libraries for some reasons like best performance and high security. Here is my suggestion. hope to be useful for you:
using System.Data.SqlClient;
...
string conStr = ConfigurationManager.ConnectionStrings["MembersConnectionString"].ConnectionString;
string sql = "SELECT * FROM Members where Username = #user and Password = #pass";
SqlParameter pUser = new SqlParameter("#user", TextBoxSignUser.Text);
SqlParameter pPass = new SqlParameter("#pass", TextBoxSignPass.Text);
using (SqlConnection con = new SqlConnection(conStr))
{
using (SqlCommand cmd = new SqlCommand(sql, con))
{
cmd.Parameters.Add(pUser);
cmd.Parameters.Add(pPass);
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.Read())
{
// Successfully signed in
// Also you can access your fields' value using:
// 1. its index (e.x. reader[0])
// 2. or its name: (e.x. reader["Username"])
}
else
{
// Login failed
}
}
}
}

SQL Requests. Working with text boxes

Not working request. What could be the problem? Before that he wrote through CommandText, all worked well.
Code:
private void buttonSearch_Click(object sender, EventArgs e)
{
string constring = #"Data Source=(LocalDB)\v11.0;AttachDbFilename=C:\Users\HomePC\Desktop\Lab2 DB\Lab2 DB\ResearchDB.mdf;Integrated Security=True";
using (SqlConnection con = new SqlConnection(constring))
{
using (SqlCommand cmd = new SqlCommand("SELECT * FROM '"+comboBox1.SelectedItem.ToString()+"' WHERE '"+ comboBox2.SelectedItem.ToString() +"' = '"+ textBox1.Text +"'", con))
{
cmd.CommandType = CommandType.Text;
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
using (DataTable dt = new DataTable())
{
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
}
}
}
}
It'd help if you provided an error, but one obvious issue is that you're not opening the connection.
You can open the connection right after you set the CommandType.
cmd.CommandType = CommandType.Text;
con.Open();
Also, I'd recommend parameterizing your query. It's more secure, and cuts down on potential typos.
using (var cmd = new SqlCommand(
"SELECT * FROM '" + comboBox1.SelectedItem.ToString() + "' WHERE '" + comboBox2.SelectedItem.ToString() + "' = #your_textbox_value", con))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#your_textbox_value", textBox1.Text);
con.Open();
...

Categories