SQL Server database query - c#

I have used the standard user tables that ASP.net setup and I'm looking to be able to delete users. To do this first off I need to delete the user id from a table called memberships and then delete the user. To do this I have 2 text boxes setup one for user id and other for user name.
Any ideas of a T-SQL statement that will delete the membership user id first and then move onto the delete username this is my statement so far
else
{
try
{
connection.Open();
cmd = new SqlCommand("DELETE from Membershio
WHERE UserId ='" + deleteuserIDbox.Text + "'", connection);
cmd = new SqlCommand("DELETE from Users WHERE UserName ='" + deleteuserbox.Text + "'", connection);
cmd.ExecuteNonQuery();
update.Text = "Your data has been removed";
}
catch
{
update.Text = "Your data has not been deleted";
}
}
The two tables are related hence I need to delete the user id first and then the username
any help greatly appricated

If understand it right, your input method has serious issues.
For example,
UserID UserName
1 testUser
2 testUser2
With the logic in your application; I can enter "1" into deleteuserIDbox and "testUser2" into deleteuserbox which in turn would remove userID 1 but not username "testUser".
If you didn't do it already, you need to associate those two tables using Foreign Key on UserID. So the linkage is persisted with UserID field.
Another issue is, you are directly executing the query with the input from user thus enabling the possiblity of sql injection.
About your query, you can put " cmd.ExecuteNonQuery();" between your two cmd statements.

To use your current code, you will need to execute the first query, then set the CommandText for the second query and execute that.
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "DELETE FROM Membership WHERE UserID = #UserID";
cmd.Parameters.AddWithValue("#UserID", deleteuserIDbox.Text);
connection.Open();
cmd.ExecuteNonQuery();
cmd.Paramters.Clear();
cmd.CommandText = "DELETE from Users WHERE UserName = #UserName";
cmd.Parameters.AddWithValue("#UserName", deleteuserbox.Text);
cmd.ExecuteNonQuery();
}
Another option is to use a stored procedure that would allow you to run the two queries together.
Another option is to do cascading deletes. Here is a link on how to accomplish that.
Lastly, you are opening yourself up to SQL Injection. You should NEVER take input from a user and concatenate that data into a SQL statement. You should either use a Stored Procedure or a parameterized query(like I used above).

You're not executing the first command:
connection.Open();
cmd = new SqlCommand("DELETE from Membershio
WHERE UserId ='" +
deleteuserIDbox.Text + "'", connection);
cmd.ExecuteNonQuery();
cmd = new SqlCommand("DELETE from Users WHERE
UserName ='" + deleteuserbox.Text +
"'", connection);
cmd.ExecuteNonQuery();
Also, these commands should be executed in a transaction.

A bit late but I only noticed your question today.
By doing this on the database you are bypassing all the good stuff! You should do this in C# by calling the Membership::DeleteUser Method
http://msdn.microsoft.com/en-us/library/5xxz7y3a.aspx
You should not mess with the internals of the Membership system at all.

Related

Syntax error in UPDATE for C# using Oledb

I am creating a simple app where users create accounts. I want for the user to be able to change their password after making the account.
I am making this in C# using Oledb.
string test = "testing";
con.Open();
OleDbCommand command = new OleDbCommand();
command.Connection = con;
string query = "UPDATE tbl_users SET password = '" + test + "' WHERE username = '" + txtLoginUsername.Text + "'";
MessageBox.Show(query);
command.CommandText = query;
command.ExecuteNonQuery();
con.Close();
I keep getting the error:
" System.Data.OleDbException: 'Syntax error in UPDATE'"
This error is occuring in the line:
command.ExecuteNonQuery();
To clarify what Hossein has answered, when you are building your query command by adding strings together, you are wide-open to SQL-injection. Please read up on it some to protect your future development.
With reference to using "parameters". This is basically referring to a place-holder value for the query, like an "insert here" instead of you hard adding parts to the query like you were wrapping single quotes before and after the values for the password and user name.
Looking at your original query
"UPDATE tbl_users SET password = '" + test + "' WHERE username = '" + txtLoginUsername.Text + "'";
What if someone put in values of
Password: What's Up
Username: O'Conner
Your final query command when concatenated with your approach would create a value
UPDATE tbl_users SET password = 'What's Up' WHERE username = 'O'Conner'
See how the literal values have now screwed-up the string from its intent.
By using the "#" values, this is telling the SQL that hey... there will be another value coming along by the name provided, please use THAT value here. In some databases, they dont use named parameters, but "?" single character instead as a place-holder and you have to add the parameters in the exact order as they appear in the statement you are trying to prepare.
One other thing of personal preference. If your column name is UserName in I would use a parameter name like "#parmUserName" so you know it is EXPLICITLY the parameter and not accidentally just doing UserName = UserName and not get the results. A few more characters, but obvious what its purpose and where coming from works.
Now, how is that applied? Take a look again at Hossein's answer. Notice the two
command.Parameters.AddWithValue("#password", "test");
command.Parameters.AddWithValue("#username", txtLoginUsername.Text);
This is where the parameters are added to the command object. Stating, where you see the #password, use the following value I am putting here, same with #username.
Good luck going forward.
Use this syntax
Use bracket for password in query
because password is reserved word
link List of reserved world
using (var connection = new OleDbConnection("Your Connection String"))
{
var query = "UPDATE tbl_users SET [password] = #password WHERE username = #username";
using (var command = new OleDbCommand(query, connection))
{
connection.Open();
command.Parameters.AddWithValue("#password", "test");
command.Parameters.AddWithValue("#username", txtLoginUsername.Text);
command.ExecuteNonQuery();
}
}

System.Data.SqlClient.SqlException: 'Incorrect syntax near 'USERNAME'.'

I'm trying to make a login and I keep getting this error:
System.Data.SqlClient.SqlException: 'Incorrect syntax near 'USERNAME'.'
Here is my code
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Omar\Documents\Data.mdf;Integrated Security=True;Connect Timeout=30");
SqlDataAdapter sda = new SqlDataAdapter("Select Count(*) From [LOGIN] were USERNAME ='" + textBox1.Text +"' and PASSWORD='"+ textBox2.Text +"'",con);
DataTable dt = new DataTable();
sda.Fill(dt);
You're getting voted down not just because this is a duplicate question but because your attempt wraps two security problems in a single piece of code.
So let's take this step by step.
1) Your actual problem is you mispelt WHERE. Your corrected code would look something like
SqlConnection con = new SqlConnection(#"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=C:\Users\Omar\Documents\Data.mdf;Integrated Security=True;Connect Timeout=30");
SqlDataAdapter sda = new SqlDataAdapter("Select Count(*) From [LOGIN] where USERNAME ='" + textBox1.Text +"' and PASSWORD='"+ textBox2.Text +"'",con);
DataTable dt = new DataTable();
sda.Fill(dt);
But you don't need a data adapter or a table, you can return a count from SQL directly. So you could do something like
string sql = "select count(*) from users where username = '" + username + "' and password = '" + password + "'";
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlCommand command = new SqlCommand(query, conn))
{
int result = (int)command.ExecuteScalar();
if (result > 0)
{
/// login sucessful
}
}
}
This would work, but you have a security vulnerability called SQL injection.
If we look at a correct login your SQL string would be
select count(*) from login where username = 'alice' and password = 'bob'
This works fine, but if I enter the classic example of SQL injection for a login page as the password, ' OR 1=1 -- then your SQL string becomes this;
select count(*) from login where username = 'alice' and password = '' OR 1=1 --'
This line of SQL will always return 1, because it's highjacked the SQL via SQL injection, adding an OR clause at the end of the statement, OR 1=1 which is always going to be true. It then uses SQL comment syntax to comment out whatever comes after it. So now I can login as anyone at all, even usernames that don't exist.
2) The correct way to build SQL strings, if you don't want to use ORMs that do this for you (and really, use an ORM, all the protection is automatic) is to use a parameterized query, which takes the input and formats it in such a way that any special characters aren't taken as SQL commands, like so
string sql = "select count(*) from login where username = #username and password = #password";
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
using (SqlCommand command = new SqlCommand(query, conn))
{
command.Parameters.Add(new SqlParameter("#username", username));
command.Parameters.Add(new SqlParameter("#password", password));
int result = (int)command.ExecuteScalar();
if (result > 0)
{
/// login sucessful
}
}
}
The parameters are in the SQL query as #parameterName, and then added with command.Parameters.Add(). Now you've avoid SQL injection
3) However this still a security problem. You're storing your passwords in plaintext. If I can gain access to your SQL database (via SQL injection, or you leaving the server open to the world) once I have a copy of the database I have your usernames and passwords and your company is going to end up on haveibeenpwned. You shouldn't be doing this. Passwords should be protected, not via encryption, but via what is called hashing and salting. This transforms the passwords into a value that is derived from it via a one way function, it takes the password, feeds it into some math, and the result out the other side represents the password, but you can't go back the other way, you can't figure out the password from the salted hash. Then when you compare logins, you compute the hash again, and use that in your comparison, in an ORM driven query or a parameterised query.
Now, with all that in mind, I'd strongly advise you to avoid doing any of this yourself. C# & ASP.NET have libraries for usernames and passwords in ASP.NET Identity. I would much rather see you use that, not just because I happen to be the PM owner for that and for .NET Security as a whole, but because it does everything right for you, without you having to do any work.
If this is for a real world application please take some time to go through the OWASP project, it has lots of examples of security problems and details on how to fix them.
Please...
learn about parameters; the code you have is open to SQL injection, which is a huge problem (especially, but not just, on a login form)
learn about not storing plain-text passwords, instead using salted cryptographic hashes
learn about IDisposable; multiple of the objects involved here are disposable and need using
don't use DataTable unless you know why you're using it - there is no reason whatsoever to use it here
learn about tools that will help do all of the above for you
and when, and only when, you have the above "down": fix the typo
Here's a version using "dapper", that covers most of this:
using (var con = SqlConnection(#"...not shown..."))
{
var hash = HashPasswordUsingUsernameAsSalt(
textBox1.Text, textBox2.Text); // impl not shown
int count = con.QuerySingle<int>(#"
select COUNT(1) from [LOGIN]
where [USERNAME]=#cn and [PW_HASH]=#hash",
new { cn = textBox1.Text, hash });
// TODO: do something with count
}
Look like on your 2nd line you have a typo for the WHERE clause.
SqlDataAdapter sda = new SqlDataAdapter("Select Count(*) From [LOGIN] WHERE USERNAME ='" + textBox1.Text +"' and PASSWORD='"+ textBox2.Text +"'",con);
However, you need to learn about SQL injection attacks since your SQL is wide open to hack attempts.

Error while executing query in C#, SQL Server: trying to update if value already present else insert

I am trying to execute a query with a condition like if username already present then update the row, else insert username and password.
This is my code below:
using (SqlCommand cmd = new SqlCommand("INSERT INTO Users(Username,Password) VALUES(#User,#password) ON DUPLICATE KEY UPDATE Username=VALUES(Username), Password=VALUES(Password)"))
{
cmd.Connection = con;
cmd.Parameters.AddWithValue("#User", TextBox3.Text);
cmd.Parameters.AddWithValue("#password", Pwd);
con.Open();
cmd.ExecuteNonQuery();
}
I got the following error:
Incorrect syntax near the keyword 'ON'.
I am not able to figure out what is wrong in this. Can anyone please help me out?
In SQL Server you need to use a query something like this:
-- check if exists (by username) - if found, update password
IF EXISTS (SELECT * FROM dbo.Users WHERE Username = #User)
UPDATE dbo.Users
SET Password = #password
WHERE Username = #User
ELSE
INSERT INTO dbo.Users(Username, Password)
VALUES(#User, #password)
And as mentioned in my comments - do not use the .AddWithValue function (see linked blog post for details) but use this instead:
cmd.Parameters.Add("#User", SqlDbType.VarChar, 100).Value = TextBox3.Text;
And also, please do not store your passwords in clear text in the database!
It looks like you're using MySQL syntax. I don't think SQL Server has ON DUPLICATE KEY. You'd probably want a MERGE statement.
#marc_s
String query = #"IF EXISTS (SELECT * FROM Users WHERE Username = # User)
UPDATE Users
SET Password = #password
WHERE Username = # User
ELSE
INSERT INTO Users(Username, Password)
VALUES(# User, #password)";
using (SqlCommand cmd = new SqlCommand(query))
I used the code you gave and used to debug points to check if the code is executing ,and it was, still it is not updating or Inserting the values .I cant run the query in SQL server cause each time i open the query window VSudio restarts,i am using trial version of Visual Studio

Determining if user login already exists in database?

I am building a web application in asp.net using C#. I have the Form where the user should register and then can login. I am having a problem in making the web app know that the name which the user picks is either "already exists" or not. If it already exists it should not insert the same name and display a message saying "user name already exists". I have tried the SqlDataReader but no luck.
protected void Register_Button_Click(object sender, EventArgs e)
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["BJ_Player_String"].ToString());
SqlCommand cmd = new SqlCommand();
SqlCommand cmd2 = new SqlCommand();
SqlDataReader data_reader;
String name = TextBox2.Text;
String date = TextBox3.Text;
try
{
conn.Open();
cmd = new SqlCommand("Insert into BJ_Player (Player_Name, D_O_B) Values (#Player_name, #D_O_B)", conn);
cmd = new SqlCommand("Select Player_Name from BJ_Player WHERE Player_Name = #Player_name", conn);
cmd.Parameters.Add("#Player_name", SqlDbType.NVarChar).Value = name;
cmd.Parameters.Add("#D_O_B", SqlDbType.Date).Value = date;
cmd.Connection = conn;
data_reader = cmd.ExecuteReader();
cmd.ExecuteNonQuery();
if (data_reader.HasRows)
{
lblPlayerNameExists.Visible = true;
}
else
{
// do nothing
}
}
Make Player_Name unique in database then it will give you exception when you try to insert. You have to use unique constraint.
You have to give command type also and check you assigned both queries to same cmd object
in your code you're inserting data in your DB and then you are examining that the name is the same or not.
first you should search the name in your DB and then if there isn't any record with that name ,you should add your record.
I usually do it in one of two ways:
Create stored procedure that will check for name uniqueness and insert new record if everything is ok. It should return status as numeric code that you will check.
Check for name uniqueness before saving it using as a part of validation process.
Using the merge statement may help with this. Merge performs insert, update, or delete operations on a target table based on the results of a join with a source table.
Basically it inserts when needed, and updates when needed. Often times referred to as an upsert. but it gets the job done.
Here is a link to a site explaining how to use merge. Looks like a good article.
http://www.kodyaz.com/articles/sql-server-2008-t-sql-merge-statement-example.aspx
If you would like to write a model function to do that then
Leave it for ajax check which is pretty similar to the second
method
Issue "Select username from DB-table" to retrieve
usernames then check the username input against them before
displaying a view to report a problem if any or showing a message to
tell the user that "this name is valid", for example.

How to save a SQL "Select" result in a variable in C#

I'm using Visual C# connected to MySQL for study purposes and I'm stuck in throwing an error to the user when he types a username that already exists.
Current code to put things into the database (it may be useless, once my question may be much more about SQL):
s = new sql(); // This calls a class that works as an adapter to connect form with the database
Conn = s.Connection;
Conn.Open();
coma = Conn.CreateCommand();
coma.CommandText = "INSERT INTO test.test (`user`,`password`) VALUES ('"+username.Text+"','"+password.Text+"');";
coma.ExecuteNonQuery();
What I want to do it compare "username.Text" ("username" is a TextBox) with the values on database's "test" table and, if some value match, evoke a MessageBox.Show("Hey guy, this username is already in use! Try something different)
Some points about your code sample
You want to be sure that you dispose of your connection and command objects. For my answer, I've wrapped them in using statements which will take care of that for me.
You do not want to go to the database with unsanitized inputs. I am going to use parameterized queries in the example.
It's not a good idea to store passwords in plain text. I am not going to demonstrate more secure techniques, just know to look for information about encrypting passwords, salt keys, etc.
And now for some code. In this, I'm using OleDb objects, retrofit to your particular database. And, of course, provide appropriate names to tables, columns, etc.
using (OleDbConnection connection = SomeMethodReturningConnection())
using (OleDbCommand command = SomeMethodReturningCommand())
{
command.Parameters.Add(new OleDbParameter("#username", username));
command.CommandText = "Select Count(*) From Users where Username = #username";
connection.Open();
int output = (int)command.ExecuteScalar();
if (output > 0)
{
// username already exists, provide appropriate action
}
else
{
// perform insert
// note: #username parameter already exists, do not need to add again
command.Parameters.Add(new OleDbParameter("#password", password));
command.CommandText = "Insert Into Users (Username, Password) Values (#username, #password)";
command.ExecuteNonQuery();
}
}
Thank you Anthony! Your answer put me on the right track. Although there is something that the people who will read this post should change from your code in order to get it working with Odbc connectors: the way as parameters are parsed and the way as the textbox content is extracted:
using (OdbcConnection connection = SomeMethodReturningConnection())
using (OdbcCommand command = SomeMethodReturningCommand())
{
command.Parameters.Add(new OdbcParameter("#username", username.Text));
command.CommandText = "Select Count(*) From Users where Username = ?";
connection.Open();
int output = (int)command.ExecuteScalar();
if (output > 0)
{
// username already exists, provide appropriate action
}
else
{
// perform insert
// note: #username parameter already exists, do not need to add again
command.Parameters.Add(new OdbcParameter("#password", password.Text));
command.CommandText = "Insert Into Users (Username, Password) Values (?,?)**";
command.ExecuteNonQuery();
}
}
Thank you anyway!

Categories