MySQL Change "user" table entry via WinForms C# - c#

Quick question - is it possible to change the password of a user that has been entered into the "user" table under the MySQL database via a WinForm app?
I've been inserting and selecting data from a database I created, but if I ever wanted to change the MySQL password, I was wondering if this is possible via C#. Reason I say this is because ATM the connectionstring is hard-coded to take the username and password (maybe someone can give advice on how not to store the password in the connection string in App.config too).
Thanks :)

Take something like this post and change the statement in the command string to use an ALTER USER instead:
using(MySqlConnection Connection = new MySqlConnection("SERVER=localhost;UID=root;"))
using(MySqlCommand Command = new MySqlCommand("ALTER USER 'username'#'localhost' IDENTIFIED BY 'password';", Connection))
{
Connection.Open();
Command.ExecuteNonQuery();
}

Related

Exception thrown: 'System.Data.SqlClient.SqlException' in System.Data.dll when trying to make simple insertion into SQL Server database

I'm new to C# and I have encountered error when trying to create a new user from my C# project and insert into the database. I kept encountering the following error when running the project:
Exception thrown: System.Data.SqlClient.SqlException' in System.Data.dll
but can't seem to find which part of the code went wrong. I have tried googling for similar solutions but have not been of help.
The following is my database and table from SQL Server Management Studio:
The following is the connection string in my web.config file to connect to the SQL Server database:
<connectionStrings>
<add name="con" connectionString="Data Source=XXX-091220MI02\SQLEXPRESS;Initial Catalog=serviceportal;Integrated Security=true"/>
</connectionStrings>
The following is the my code in Visual Studio when trying to insert into database:
protected void Button1_Click(object sender, EventArgs e)
{
try
{
SqlConnection conn = new SqlConnection(strcon);
if(conn.State == ConnectionState.Closed)
{
conn.Open();
}
SqlCommand cmd = new SqlCommand("INSERT INTO user (username, password) VALUES (#user, #pass)", conn);
System.Diagnostics.Debug.WriteLine("Textbox 1 Text: " + TextBox1.Text.Trim());
System.Diagnostics.Debug.WriteLine("Textbox 2 Text: " + TextBox2.Text.Trim());
cmd.Parameters.AddWithValue("#user", TextBox1.Text.Trim());
cmd.Parameters.AddWithValue("#pass", TextBox2.Text.Trim());
cmd.ExecuteNonQuery();
conn.Close();
Response.Write("<script>alert('Sign Up Successful. Redirecting to Login Page ...');</script>");
Response.Redirect("Login.aspx");
}
catch(Exception ex)
{
Response.Write("<script>alert('" + ex.StackTrace +"');</script>");
}
}
Please change the insert statement as 'user' is keywords in database.
INSERT INTO [dbo].[user] (COLUMNS) VALUES();
Please ensure your connection string is correct.
Try using this -
insert into [dbo].[user] (username, password) values (#user, #pass)
USER is a reserved word for sqlserver; if you call your table User you'll have to quote its name when using it. Consider renaming your table to Users, or quoting it ( insert into [user] ). One nice thing about giving tables plural names is they seldom collide with keywords, (though "should table names be singular or plural is a bit of a holy war" ..)
Bad:
Good:
Note: the fact that those images show a create table statement is immaterial; using "user" without quoting it doesn't work in an insert in the same way it doesn't work in a create
Some other points:
consider avoiding AddWithValue on SQLServer - https://www.dbdelta.com/addwithvalue-is-evil/ - I don't care so much about insert statements but it causes problems with select statements
give your textboxes etc proper names. It takes a few seconds to rename a control, do not stick with the default "TextBox1" name- by the time you've added a hundred controls your code will be meaningless and hard to follow
do not store passwords in plain text. Read up on what hashing and salting is, and always always always salt-hash your passwords. Code like this coupled up with human nature of reusing passwords is the reason why password lists and rainbow tables exist and why one hack leads to many. Once someone has hacked your site and scraped all the user's carefully chosen mega secure 16 character random char passwords into a list they can just try them anywhere else to get a win. You can't turn round and say "well it's their fault for reusing a password" - there are two faults, but storing the password in plain text is the bigger one (because it's easier to fix than human nature). If you don't want to store user data securely, hand the problem of authentication/authorisation off to someone else, like auth0 or Microsoft azure AD
if you're learning db interaction, using Dapper or EF might be the better way to go; this is really low level code you're writing- it's a lot of lines/effort for very little overall action. In EF all your code would have looked something like:
db.Users.Add(new User { Username = userTextbox.Text, Password = passTextBox.Text });
db.SaveChanges();
...and it would have worked, because EF knows how to quote table names

Data is not showing/updating in the SQLite table when the data is inserted through my C# code

Currently, I have been doing some simple coding related to SQL and C#. I have created this a registration form which will store the data, username and password, in an SQLite database. This is the code that I am currently using:
private void AddLoginInfo(string username, string password)
{
auth = new Authentication();
auth.getConnection();
using (SQLiteConnection con = new SQLiteConnection(auth.connectionstring))
{
SQLiteCommand cmd = new SQLiteCommand();
con.Open();
string que = #"INSERT INTO LoginInfo(Username, Password) VALUES (#username, #password)";
cmd.CommandText = que;
cmd.Connection = con;
cmd.Parameters.Add(new SQLiteParameter("#Username", username));
cmd.Parameters.Add(new SQLiteParameter("#Password", password));
cmd.ExecuteNonQuery();
MessageBox.Show("Account Created!");
}
}
This code currently works and does add to the correct table in the database however whenever a new user is added. The user information can be used to login but it does not show within the table, which is viewed using DB Browser for SQLite.
For example, if I create a new user; 'admin' as the username and 'password' as the password, through the form, I get the message box saying 'Account Created' and I can use that very account to login. However, if I go view that very data in the DB browser the data doesn't show even after refreshing the table.
After doing some digging, I found this and saw that they were using sqlCommand.Parameters.AddWithValue so I tried this within my code:
SQLiteCommand cmd = new SQLiteCommand(#"INSERT INTO LoginInfo(Username, Password) VALUES (#username, #password)", con);
cmd.Parameters.AddWithValue(new SQLiteParameter("#Username", txtBoxUsername.Text));
I tried this and I got a CS7036 error. Then I realised that they had not used the new SQLiteParameter() part and so I removed it cmd.Parameters.AddWithValue("#Username", txtBoxUsername.Text); and tried again but it still wouldn't update in the table but the data could still be used to log in.
I have also found a similar post but no one had answered it.
Now I don't know what to do, so I am asking for your help.
I figured out what was the problem; I was checking the database that was stored in the solution but what I should have checked is the database stored in the ...\bin\debug folder. The database within the folder shows the added data.
Are you retrieving the db file from another system? i.e. Android Emulator or a network location?
Are there any other files in the folder, you are specifically looking for a filename that contains '-wal'. Additional information on SQLite Wal format
the data is actually contained in this other file. DB Browser knows to look for this file. However, if you are downloading the db to your system before you take a look, you are probably not downloading the -wal file as well.
Depending on how you are configuring your SQLite db, the limit by default for checkpoint threshold is 1kb. Until the checkpoint is triggered, the data doesn't get transferred to the main db file. There are ways to manually trigger the checkpoint, see the link I have included above.

SQL Server Express with Windows app C# [duplicate]

I am executing SQL command INSERT like this in my Visual C#.NET using MS VS 2010 Express Edition:
private void btnAdd_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(Properties.Settings.Default.loginDBConnectionString);
con.Open();
SqlCommand cmd = new SqlCommand("INSERT INTO tblEmp (ID, firstname, lastname, email, position) VALUES ('"+textBox1.Text+"','"+textBox2.Text+"', '"+textBox3.Text+"', '"+textBox4.Text+"', '"+comboBox1.Text+"')", con);
cmd.ExecuteNonQuery();
con.Close();
MessageBox.Show("Data Added!");
}
When executing this, the MessageBox showed up which means the execution was successful. But, when I checked on the table , the data that I am trying to insert before isn't appear at all.
I have one database (loginDB.mdf) with 2 tables inside :
- TblLogin - contains username and password for login purpose which executed successfully.
- tblEmp - contains employee data, this is the one that I tried to insert data to.
What I don't understand is why the MessageBox appear when in fact none inserted into my tblEmp.
EDIT : ConnectionString to loginDB.mdf :
Data Source=.\SQLEXPRESS;AttachDbFilename="C:\Users\Andreas\documents\visual studio 2010\Projects\LoginApplication\LoginApplication\loginDB.mdf";Integrated Security=True;User Instance=True
The database name is loginDB.mdf instead of logindatabase.mdf as previously written. I changed it to loginDB.mdf just to test it, but still no changes appear.
If your c# code executes without any exceptions, it updates the database too. You have probably used AttachDbFilename=|DataDirectory|\yourDB.mdf in your ConnectionString, that means the databse that is updated is located in the subfolder BIN\DEBUG folder of your project. If you want to see the updated data just attach the database located in the bin/debug folder in ssms.
for more details read this post.
Also make sure your table in server explorer is not already open, if it is already open you must refresh it to show updated data. Please note:as mentioned in the comments you should always use parameterized queries to avoid Sql Injection.

Database failed to open - Login failed for User

I'm currently writing code to save information to a database.
I think I'm at now approaching the last hurdle for getting it to work.
My issue is that when I click save I get a message box saying, Cannot open Database [Database file path] requested by the login. The login failed. Login failed for 'User-PC\User'.
However I didn't create any login details for the database as in the future I want anyone who uses the program to be able to log information into it.
I'm not quite sure where to look to solve the issue, but I am currently downloading SSMS to see if I can fix it there?
Any help would be great, thanks!
My code is,
string constring = "Data Source=(LocalDB)\MSSQLLocalDB;Initial Catalog=c: \users\user\documents\visual studio 2015\Projects\LossApplication\LossApplication\LossDB.mdf;Integrated Security=Yes; Trusted_Connection=True; ";
string query = " insert into LossDB.LossTable (lossid,Equipment, Event, responsinility, start) values(#lossid, #equipment, #Cause, #reason, #start) ;";
SqlConnection conLossDB = new SqlConnection(constring);
SqlCommand cmdLossDB = new SqlCommand(query, conLossDB);
cmdLossDB.Parameters.AddWithValue("#lossid", textBox1.Text);
cmdLossDB.Parameters.AddWithValue("#Equipment", comboBox1.Text);
cmdLossDB.Parameters.AddWithValue("#Cause", comboBox2.Text);
cmdLossDB.Parameters.AddWithValue("#Reason", comboBox3.Text);
cmdLossDB.Parameters.AddWithValue("#start", dateTimePicker1.Text);
//Defines which boxes to read in order to input the text from the defined boxes into the corresponding columns
SqlDataReader myReader;
try
{
conLossDB.Open();
myReader = cmdLossDB.ExecuteReader();
MessageBox.Show("Loss Entry Saved");
//Opens the database and carries out the defined command outlined in the code above
while (myReader.Read())
{
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Using Integrated Security means Windows Authentication mode of the sql server, there must be a valid Windows user that has access to the database. If you want to use this mode and give access to all user on the computer, you can configure Windows Users group (to which all users typically belongs to) to have access to your database (see Security->Logins in your database configuration).
Another approach is to create a SQL user and user SQL Server Authentication mode. Then you use this user login and password to get access to the database regardless of Windows user. In this case your connection string will looks like
(LocalDB)\MSSQLLocalDB;Initial Catalog=<path>\LossDB.mdf;User ID=<UserLogin>;Password=<***>;Trusted_Connection=True;

How can I display a message if a value already exists in database?

I am currently writing my first .Net & C# application with Visual Studio, and have a need to write generated values to MySQL from the application.
At present, I can write values fine - but I need to be able to check to see if a value exists and display that line if it does exist, otherwise insert new line to table. My connection string is defined at the top of the form.
I have the following defined already, and it writes to the database successfully if no duplicate values exist in the LicenseKey column. If a duplicate exists, it throws an unhandled exception.
private void SaveDetails()
{
// MySQL 'insert' command
string InsertNewLicense = "insert into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values('" +this.textBoxLicenseeName.Text+ "','" +this.textBoxComputerName.Text+ "','" +this.textBoxContactName.Text+ "','" +this.textBoxContactEmail.Text+ "','" +this.textBoxLicenseKey.Text+ "','" +this.textBoxCreationDate.Text+ "');";
//MySQL instance details
MySqlConnection InsertLicenseDetails = new MySqlConnection(LicenseDatabaseConnection);
//MySQL command execution
MySqlCommand InsertCommand = new MySqlCommand(InsertNewLicense, InsertLicenseDetails);
// Handles command outputs.
MySqlDataReader InsertReader;
//Opens connection to run query on database
InsertLicenseDetails.Open();
// Here our query will be executed and data saved into the database.
MessageBox.Show("License Details Saved. Please ensure you have emailed the license to the customer.");
while (InsertReader.Read())
{
}
InsertLicenseDetails.Close();
}
What I want to happen is for a check to be run on the LicenseKey column to see if the value exists, before different actions are taken.
If the value does not exist, I would like to insert the new line to the table (like my existing command does).
If, however, the value does exist, I would like to pop up a form showing the values from the line that the duplicate appears in as a form.
Where would I put in an event handler to read MySQLException values? What exception would I have to respond to for a duplicate value or no database response?
I agree with what the others have said in their comments, you could change the SQL Query to do the check instead of having 2.
IF(SELECT ... WHERE A = B)
RETURN THAT THE VALUE ALREADY EXISTS
ELSE
INSERT NEW VALUE
Also there was a good comment about SQL Injection and parameterized queries. The query string should look a bit more like
INSERT into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values(#LicenseeName, #ComputerName, #ContactName ...);
and your SqlCommand be parameterized
InsertCommand.Paramaters.AddWithValue("#LicenseeName", this.textBoxLicenseeName.Text);
InsertCommand.Paramaters.AddWithValue("#ComputerName", this.textBoxComputerName.Text);
...
That should be a good start to get you going.
After looking at the queries for a while I decided to try a different tack - instead of using a direct check if it's there, I opted to use a count(*) query. When I click the save button on the form, the buttonClick_event calls SaveDetails(), which runs the following:
private void SaveDetails()
{
string InsertNewLicense = "INSERT into BCOM.LicenseDetails(LicenseeName,ComputerName,ContactName,ContactEmail,LicenseKey,CreationDate) values(#LicenseeName, #ComputerName, #ContactName, #ContactEmail, #LicenseKey, #CreationDate)";
string LicenseExistence = "SELECT COUNT(*) FROM BCOM.LicenseDetails WHERE LicenseKey LIKE #LicenseKey";
MySqlConnection LicenseDetails = new MySqlConnection(LicenseDatabaseConnection);
MySqlCommand InsertCommand = new MySqlCommand(InsertNewLicense, LicenseDetails);
InsertCommand.Parameters.AddWithValue("#LicenseeName", this.textBoxLicenseeName.Text);
InsertCommand.Parameters.AddWithValue("#ComputerName", this.textBoxComputerName.Text);
InsertCommand.Parameters.AddWithValue("#ContactName", this.textBoxContactName.Text);
InsertCommand.Parameters.AddWithValue("#ContactEmail", this.textBoxContactEmail.Text);
InsertCommand.Parameters.AddWithValue("#LicenseKey", this.textBoxLicenseKey.Text);
InsertCommand.Parameters.AddWithValue("#CreationDate", this.textBoxCreationDate.Text);
MySqlCommand QueryCommand = new MySqlCommand(LicenseExistence, LicenseDetails);
QueryCommand.Parameters.AddWithValue("#LicenseKey", this.textBoxLicenseKey.Text);
MySqlDataReader InsertReader;
LicenseDetails.Open();
if ((int)(long)QueryCommand.ExecuteScalar() >0)
{
MessageBox.Show("This license already exists in the database.");
}
else
{
InsertReader = InsertCommand.ExecuteReader();
MessageBox.Show("License Details Saved. Please ensure you have emailed the license to the customer.");
while (InsertReader.Read())
{
}
}
LicenseDetails.Close();
So, if the query against the license keys returns with any results at all (more than 0 rows returned), a messagebox pops up showing that the key already exists. If the resultant number of rows is 0, the insert command gets run.
This was figured out with a look through MySQL command notes, testing with phpMyAdmin, matching against existing projects online, and support from the following:
The SELECT query was figured out with great support from #Seige.
The query was parameterized with help from Seige, following on from the advice of Sani Huttunen. Many thanks to them both.
Changing to the count method was done on the advice of a fellow coder in another community online - a good friend and brilliant coder.

Categories