So I have code that stores an UPDATE query in a string, then I parameter bind the update query and then execute and update it, this is my code:
string query = "UPDATE Users SET first_name = '#firstname' WHERE ID = #id";
updateUserDS.UpdateParameters.Add("id", HTTPContext.Current.Session["ColumnID"].ToString());
updateUserDS.UpdateParameters.Add("firstname", txt_firstname.Text);
updateUserDS.UpdateCommand = query;
updateUserDS.Update();
However when I change my string query to:
string query = "UPDATE Users SET first_name = 'name' WHERE ID = 44";
It works perfectly and updates my table, so I am guessing its something to do with how I have binded the query, does anyone realise anything where I have gone wrong?
BTW: The Session["ColumnID"] is being retrieved perfectly as it states 44 in the stack trace
Remove the single quotes from #firstname:
string query = "UPDATE Users SET first_name = #firstname WHERE ID = #id";
updateUserDS.Parameters.AddWithValue("#firstname", first_name);
updateUserDS.Parameters.AddWithValue("#id", HTTPContext.Current.Session["ColumnID"].ToString());
EDIT:
Assuming you are using SQL Server as database try like this:
SqlCommand sqlComm = new SqlCommand();
sqlComm.CommandText = #"UPDATE Users SET first_name = #firstname WHERE ID = #id";
sqlComm.Parameters.Add("#firstname", SqlDbType.VarChar);
sqlComm.Parameters["#firstname"].Value = txt_firstname.Text;
sqlComm.Parameters.Add("#id", SqlDbType.VarChar);
sqlComm.Parameters["#id"].Value = HTTPContext.Current.Session["ColumnID"].ToString();
using (SqlConnection sqlConn = new SqlConnection(connection string here);)
{
sqlComm.Connection = sqlConn;
sqlConn.Open();
sqlComm.ExecuteNonQuery();
}
I'd rewrite this as to use OldDbCommand and OleDbConnection instead of SqlDataSource. It doesn't depend on System.Web assembly (smaller deployment size for non-web situations), there's fewer layers in the stack trace (faster), and it's how most people are used to using ADO.NET.
var command = new OleDbCommand("UPDATE Users SET first_name = ? WHERE ID = ?");
command.Parameters.AddWithValue("id", Session["ColumnID"].ToString());
command.Parameters.AddWithValue("firstname", txt_firstname.Text);
using (var connection = new OleDbConnection(connectionString))
{
command.Connection = connection;
connection.Open();
command.ExecuteNonQuery();
}
Another note, you seem to be doing your database access directly in the UI layer! That's hard to test, and not very flexible. It'd be better if you moved all data access code into a separate class library, and then communicate back and forth by passing Models, which are code representations of database entities.
You're also using Access, which isn't really that great of a database system. MS SQL Server is much preferable.
That might look something like this:
Code Behind
DataLayer DB {get; set;}
protected void Page_Load(object sender, EventArgs e)
{
DB = new DataLayer("connectionstring");
}
protected void SubmitBtn_Click(object sender, EventArgs e)
{
SystemUser user = new SystemUser()
{
Id = Session["ColumnID"].ToString(),
FirstName = txt_firstname.Text
}
DB.UpdateUser(user);
}
Data Layer
public class DataLayer
{
string ConnectionString {get; set;}
public DataLayer(string connectionString)
{
ConnectionString = connectionString;
}
public void UpdateUser(SystemUser user)
{
var command = new SqlCommand("UPDATE Users SET first_name = #firstname WHERE ID = #id");
command.Parameters.AddWithValue("id", user.Id);
command.Parameters.AddWithValue("firstname", user.FirstName);
using (var connection = new SqlConnection(ConnectionString))
{
command.Connection = connection;
connection.Open();
command.ExecuteNonQuery();
}
}
public void ChangePassword(string UserId, string password)
{
//hash and change password here
}
}
Models
public class SystemUser
{
public string Id {get; set;}
public string FirstName {get; set;}
}
Related
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";
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
I am trying to update a databse entry under a specific id in my table when the users enter their ID number in a textBox.
At the moment it updates but updates all entries in my table except the entry containing the users ID number.
This is the code I am currently using:
private void Button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(#"Data Source=DEVELOPMENT\ACCESSCONTROL;Initial Catalog=ACCESSCONTROL;User ID=sa;Password=P#55w0rd123");
SqlCommand check_User_Name = new SqlCommand("SELECT Id FROM NewVisitor WHERE (IDNumber = #IDNumber)", con);
check_User_Name.Parameters.AddWithValue("#IDNumber", idNumber_TxtBox.Text);
con.Open();
int UserExist = (int)check_User_Name.ExecuteScalar();
if (UserExist > 0)
{
var connetionString = #"Data Source=DEVELOPMENT\ACCESSCONTROL;Initial Catalog=ACCESSCONTROL;User ID=sa;Password=P#55w0rd123";
var sql = "UPDATE NewVisitor SET PersonVisit = #PersonVisit, PurposeVisit = #PurposeVisit, Duration = #Duration, Disclaimer = #Disclaimer";
try
{
using (var connection = new SqlConnection(connetionString))
{
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.Add("#PersonVisit", SqlDbType.NVarChar).Value = personVisiting_TxtBox.Text;
command.Parameters.Add("#PurposeVisit", SqlDbType.NVarChar).Value = purposeOfVisit_CMBox.SelectedItem;
command.Parameters.Add("#Duration", SqlDbType.Date).Value = duration_dateTimePicker1.Value.Date;
command.Parameters.Add("#Disclaimer", SqlDbType.NVarChar).Value = disclaimer_CHKBox.Checked;
connection.Open();
command.ExecuteNonQuery();
}
}
}
The whole table has many more fields but would like to just update the above fields within that specific ID.
Thanks
You forgot the WHERE clause on the UPDATE statement, telling it specifically which records to update. It sounds like you just want to add the exact same WHERE clause that you have on your SELECT:
var sql = "UPDATE NewVisitor SET PersonVisit = #PersonVisit, PurposeVisit = #PurposeVisit, Duration = #Duration, Disclaimer = #Disclaimer WHERE (IDNumber = #IDNumber)";
And don't forget to add the paramter for it:
command.Parameters.Add("#IDNumber", SqlDbType.Int).Value = idNumber_TxtBox.Text;
You may need to convert the input value to an integer first, I'm not 100% certain (it's been a while since I've had to use ADO.NET directly). Something like this:
if (!int.TryParse(idNumber_TxtBox.Text, out var idNumber))
{
// input wasn't an integer, handle the error
}
command.Parameters.Add("#IDNumber", SqlDbType.Int).Value = idNumber;
I'm new at coding and I need help for a school project.
I want to update a database using MySQL but I can't find out how to get the update working.
I have googled a bit but I haven't been able to find a solution so I figured I'd ask the question on this site.
I have successfully made a connection to the database and show the contents in a data grid. The connection has a name: "conn". If anyone knows a way on how I can get the update to work I'd be happy to hear from you!
This is my XAML.CS code:
public void Click_btnBewerk(object sender, RoutedEventArgs e)
{
string vzitter2 = txtVZitter.Text;
string info2 = txtInfo.Text;
string zetels2 = txtZetels.Text;
string stroming2 = txtStroming.Text;
string partij = cmPartijen.Text;
conn.Updateinfo();
}
This is my DBconn code:
public DataView Updateinfo()
{
conn.Open();
MySqlCommand command = conn.CreateCommand();
command.CommandText = "UPDATE partijen SET fvzitter='vzitter2', info='info2', zetels='zetels2', stroming='stroming2' WHERE partij='partij'";
MySqlDataReader reader = command.ExecuteReader();
DataTable dtData = new DataTable();
dtData.Load(reader);
conn.Close();
return dtData.DefaultView;
}
you are doing a Reading action on the db instead an update.
Just replace your code with this
public void Updateinfo()
{
conn.Open();
MySqlCommand command = conn.CreateCommand();
command.CommandText = "UPDATE partijen SET fvzitter='vzitter2', info='info2', zetels='zetels2', stroming='stroming2' WHERE partij='partij'";
command.ExecuteNonQuery();
conn.Close();
}
if you want pass the variables to the updateinfo method just do it
private void Updateinfo(string fvzitter, string info, string zetels, string stroming, string partij)
{
string query = "UPDATE partijen SET fvzitter=#fvzitter, info=#info, zetels=#zetels, stroming=#stroming WHERE partij=#partij"
conn.Open();
MySqlCommand command = conn.CreateCommand();
command.CommandText = query;
command.Parameters.AddWithValue("#fvzitter", fvzitter);
command.Parameters.AddWithValue("#info", info);
command.Parameters.AddWithValue("#zetels", zetels);
command.Parameters.AddWithValue("#stroming", stroming);
command.Parameters.AddWithValue("#partij", partij);
command.ExecuteNonQuery();
conn.Close();
}
I need to send the ID of a logged in user to multiple windows forms but can't figure it out. How can I call the variable on multiple forms?
private void btnUpdate_Click(object sender, EventArgs e)
using(var con = new SqlConnection("connectionstring"))
{
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 connection
con.Open();
// Add your parameters
cmd.Parameters.AddWithValue("#username", txtUsername.Text);
cmd.Parameters.AddWithValue("#password", txtPassword.Text);
// Get ID
var sqlid = Convert.ToInt32(cmd.ExecuteScalar());
}
}
Ive been stumped for hours and can't proceed
How can I call the variable on multiple forms?
Take the code out of your button click event. Put it in a class within a shared library that can be accessed by multiple forms.
You should also create a User class (and a UserRepository) that you pass around instead of just an ID with no context.
This is what D Stanley was talking about.
The User data-structure
public class MyUser
{
public int ID;
public string UserName;
public MyUser(int id, string userName)
{
ID = id;
UserName = userName;
}
}
The database interface class
public class UserContext
{
private ConnectionString = ""
// 1st constructor you pass in connection string.
public UserContext(string connectionString)
{
ConnectionString = connectionString;
}
// 2nd constructor you use the one in the web.config file.
public UserContext()
{
ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["connectionStringName"].ConnectionString;
}
public int GetUserID(string userName, string password)
{
// declare the result variable.
MyUser result
using(var con = new SqlConnection(ConnectionString))
{
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 connection
con.Open();
// Add your parameters
cmd.Parameters.AddWithValue(userName);
cmd.Parameters.AddWithValue(password);
// Get ID
var sqlid = Convert.ToInt32(cmd.ExecuteScalar());
result = new MyUser(sqlid, userName);
}
}
return result;
}
}
Now all you have to do is create a database context object and pass in properties.
private void btnUpdate_Click(object sender, EventArgs e)
{
// database context.
UserContext UC = new UserContext();
// Get user.
MyUser currentUser = UC.GetUserID(txtUserName.Text, txtPassword.Text);
// now you can access userid from the User data-structure object.
var id = currentUser.ID;
}