So I am using a MySQL Server version 8.0.16 and if I try to let dynamically create a new user, i do receive a Error message what says: >>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax. to use near '$password' at line 1<<.
What i can't understand, becouse if i replace the Parameters with the actual value and try it with the shell it works perfectly. I let my code connect as root so and checked if the connection is open what it is. So if I stepped into the code and checked if the parameters are correct everything looked fine. I also added >>'<< at the beginning and end of thext strings that should replace the parameters but it didn't changed the error or what happened.
public bool CreateNewUser(string name, string password, string host)
{
string query = "CREATE USER $name#$host IDENTIFIED BY $password;";
List<MySqlParameter> mies = new List<MySqlParameter>
{
new MySqlParameter("$name", name),
new MySqlParameter("$password", password),
new MySqlParameter("$host", host)
};
return InsertIntoQuery(query, mies);
}
//The InsertIntoQuery looks like this
private bool InsertIntoQuery(string sql, List<MySqlParameter> sqlParameters = null)
{
bool retBl = false;
try
{
using (var SqlConnection = new MySqlConnection(ConnectionStr))
{
SqlConnection.Open();
using (var cmd = new MySqlCommand(sql, SqlConnection))
{
if (sqlParameters != null)
foreach (var item in sqlParameters)
cmd.Parameters.AddWithValue(item.ParameterName, item.Value);
cmd.Prepare();
var retValNonQuery = cmd.ExecuteNonQuery();
retBl = (retValNonQuery > 0) ? true : false;
}
}
}
catch (Exception e)
{
MessageBox.Show("Error: " + e.Message);
}
return retBl;
}
I would expect it to create a new user but it doesn't.
No, for CREATE USER command I don't think you can pass command parameter likewise. Rather substitute the value as is like below using string interpolation syntax.
string query = $"CREATE USER '{name}#{host} IDENTIFIED BY {password}";
For an older C# version consider using string.Format()
string query = string.Format("CREATE USER '{0}'#'{1}' IDENTIFIED BY '{2}'",name,host,password);
Per OP's comment: You can't cause it's not a DML operation. If you are worried about SQL Injection probably cause input value is coming from user input then you will have sanitize it someway and moreover if you observe the input are quoted.
Again, I would suggest that this kind of admin operation should go in a DB bootstrap script and not in your application code.
Related
I am trying to learn C# and I'm writing a system where you have to log in, I'm storing the data in a database and loading in with code. The data is loaded in with no errors and I can Console.WriteLine it and it's all fine, but when I run comparison on it it always fails. Here is the relevant code.
Edit: I have tried without using the $ in the string comparison and it still doesn't work
private void login_button_Click(object sender, EventArgs e)
{
// App.config stores configuration data
// System.Data.SqlClient provides classes
// for accessing a SQL Server DB
// connectionString defines the DB name, and
// other parameters for connecting to the DB
// Configurationmanager provides access to
// config data in App.config
string provider = ConfigurationManager.AppSettings["provider"];
string connectionString = ConfigurationManager.AppSettings["connectionString"];
// DbProviderFactories generates an
// instance of a DbProviderFactory
DbProviderFactory factory = DbProviderFactories.GetFactory(provider);
// The DBConnection represents the DB connection
using (DbConnection connection =
factory.CreateConnection())
{
// Check if a connection was made
if (connection == null)
{
Console.WriteLine("Connection Error");
Console.ReadLine();
return;
}
// The DB data needed to open the correct DB
connection.ConnectionString = connectionString;
// Open the DB connection
connection.Open();
// Allows you to pass queries to the DB
DbCommand command = factory.CreateCommand();
if (command == null)
{
return;
}
// Set the DB connection for commands
command.Connection = connection;
// The query you want to issue
command.CommandText = $"SELECT * FROM Users WHERE Username = '{username_input.Text}'";
// DbDataReader reads the row results
// from the query
using (DbDataReader dataReader = command.ExecuteReader())
{
dataReader.Read();
//while(dataReader.Read())
//{
if ($"{password_input.Text}" ==$"{dataReader["Password"]}")
{
MessageBox.Show("Logged in");
}
else
{
MessageBox.Show("Invalid Credentials!");
}
//}
}
}
}
}
Always use parameters instead of string concatenation in your queries. It guards against sql injection (not applicable to MS Access) and ensures you never has issues with strings that contain escape charaters.
I notice you probably have password as plain text, never store passwords in plain text!
In this particular case using ExecuteScalar simplifies the logic (IMO). If you were to want to return data and read it using a data reader then do not use * for your return. Specify your column names instead. This will guard your code against schema changes like columns being added or column order changes.
command.CommandText = "SELECT [Password] FROM [Users] WHERE [Username] = #userName";
// using DbCommand adds a lot more code than if you were to reference a non abstract implementation when adding parameters
var param = command.CreateParameter();
param.ParameterName = "#userName";
param.Value = username_input.Text;
param.DbType = DbType.String;
param.Size = 100;
command.Parameters.Add(param);
// compared with SqlDbCommand which would be 1 line
// command.Parameters.Add("#userName", SqlDbType.VarChar, 100).Value = username_input.Text;
var result = command.ExecuteScalar()?.ToString();
if(string.Equals(password_input.Text, result, StringComparison.Ordinal))
MessageBox.Show("Logged in");
else
MessageBox.Show("Invalid Credentials!");
Start off on the right foot with learning C# with some advice Ive seen in the comments already as well some additional advice below:
Parameterize your queries at the very minimum
The below way is Open to SQL injection
command.CommandText = $"SELECT * FROM Users WHERE Username = '{username_input.Text}'";
This instead should be written as: (Keep in mind there are shorter ways to write this but I'm being explicit since you are learning)
var usernameParam = new SqlParameter("username", SqlDbType.VarChar);
usernameParam.Value = username_input.Text;
command.Parameters.Add(usernameParam);
command.CommandText = "SELECT * FROM Users WHERE Username = #username";
Secondly, debugging is your friend. You need to add a breakpoint on the line that is failing and utilize the built in Visual Studio Watchers to look at your variables. This will tell you more information than a console.writeline() and solve more problems than you might imagine.
Good morning.
I am attempting to connect to an Oracle database I have set up. before I go into detail, here's the code:
//string was slightly altered.
string connectionString = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=name)));User Id = system; Password = mypass; ";
string toReturn = "D.BUG-";
using (OracleConnection oracleConnection = new OracleConnection(connectionString))
{
oracleConnection.Open();
using (OracleCommand oracleCommand = new OracleCommand())
{
oracleCommand.Connection = oracleConnection;
oracleCommand.CommandText = "SELECT lixo FROM lixeira WHERE lixo IS NOT NULL";
oracleCommand.CommandType = CommandType.Text;
using (OracleDataReader oracleDataReader = oracleCommand.ExecuteReader())
{
//This point IS reached!
while (oracleDataReader.Read())
//This point is never reached...
toReturn += oracleDataReader.GetString(0);
}
}
}
return toReturn;
Now, I know for a fact that connecting works, and I know for a fact that the table "lixeira" can be found; I have tested this by changing that name to another name, and getting the corresponding "i can't find that table" exception.
'ORA-00942: tabela ou visualização não existe'. (Table or View does not exist)
The issue is that this code is unable to read. The same query ran through SQL Developer works:
SQL Developer screenshot of the same query
So, I'm kinda at a loss as to why oracleDataReader.Read() just never works. Am I doing something wrong?
Make sure your user/password in the connection string is the correct one.
If a table doesn't exist but exists... it probably doesn't exist for your current user (= that user has not the necessary permissions)
Previous answer is correct, I am just adding another bit.
can you replace your query as following :
SELECT lixo FROM <table owner>.lixeira WHERE lixo IS NOT NULL
This will give more appropriate error of what you are missing.
Its probably a permission (grant select) issue.
Abhi
I am just learning c# and sql server. This question has been asked a couple of times but the solutions posted don't seem to help me.
I have a table called "LoginInfo" that has a user's "email" and "pass".
In visual studio i have this method that checks a users login information
private boolean dbQueryLogin(string email, string password)
{
string com = "SELECT pass FROM LoginInfo WHERE email = XXXXX#yahoo.com";
SqlCommand command = new SqlCommand(com, conn);
SqlDataReader reader = command.ExecuteReader();
return reader.GetString(0).Equals(password);
}
This keeps on throwing the error "Additional information: The multi-part identifier "XXXX.edu" could not be bound."
The syntax looks right to me, is there anything i'm missing??
The clue is in the error message:
The multi-part identifier "XXXX.edu" could not be bound.
That strongly suggests that the problem isn't with identifying your table - it's with the bit that ends with "edu", which seems like to be an email address.
The immediate problem is that you've forgotten to quote a value. The deeper problem is that you should be using parameterized SQL anyway, to avoid SQL injection attacks, conversion problems and unreadable code. Given that the value you've given in the same code isn't the same as what's in the error message, I suspect you really have code like:
string sql = "SELECT pass FROM LoginInfo WHERE email = " + email;
Don't do that. Use parameterized SQL instead:
private boolean dbQueryLogin(string email, string password)
{
string sql = "SELECT pass FROM LoginInfo WHERE email = #email";
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(sql))
{
command.Parameters.Add("#email", SqlDbType.NVarChar).Value = email;
using (var reader = command.ExecuteReader())
{
// FIXME: What do you want to do if
// there are no matches?
reader.Read();
return reader.GetString(0) == password;
}
}
}
}
This still isn't good code though:
Don't store plain-text passwords in a database
Handle the case where there are no results
Don't build your own authentication system at all; use an existing one written by people with more experience in securing data
I've a form opened which is has loaded some sort of data (like username, CNIC, Contact no, etc etc) in Check boxes, now I want to update the data in such manner that I simply change the text in the text boxes and click on the save changes to save it. I've tried it but I am not able to do it in correct manner.
Let me show you how I've coded, the code I did in frmViewformList savechanges button is :
private void btnSaveChanges_Click(object sender, EventArgs e)
{
string sql;
string UserName;
UserName = txtUserName.Text; // saving data loaded on run time to UserName
sql = "";
sql += "UPDATE UserLogin";
sql += "SET Name = "+ //how to access data I've changed in TextBox after loading +"";
sql += "WHERE Name= " + //how to access data which was in text box right after loading + ""; //
}
I am a bit confused about how to refer to data, like the name already in the text box or the name which I have changed and how to write it in SQL query...
This question is a bit confusing, I know. Let me explain; the form is loaded, there are text boxes which is being populated with the data in database on load event, I change the data in text boxes and save on click so that the update query runs and changes the data in database as well.
I'm not able to create logic here how to do this, can any one help me out, I am sorry I am a new developer of C# that's why I am a bit confused.
You should use Sql Parameters in order to avoid SQL Injection which could leave your database vulnerable to malicious exploitation.
It's a good idea to separate the logic for performing the update to the logic where you create your query so you don't have to repeat code and so that you can maintain your code easier.
Here is an example you can reference:
public void DoWork()
{
// Build Query Use #Name Parameters instead of direct values to prevent SQL Injection
StringBuilder sql = new StringBuilder();
sql.Append("UPDATE UserLogin");
sql.Append("SET Name = #UpdatedName");
sql.Append("WHERE Name = #Name");
// Create parameters with the value you want to pass to SQL
SqlParameter name = new SqlParameter("#Name", "whatEverOldNameWas");
SqlParameter updatedName = new SqlParameter("#UpdatedName", txtUserName.Text);
Update(sql.ToString(), new [] { name, updatedName });
}
private static readonly string connectionString = "Your connection string"
private static readonly DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
public static int Update(string sql, SqlParameter[] parameters)
{
try
{
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = connectionString;
using (DbCommand command = factory.CreateCommand())
{
command.Connection = connection;
command.CommandText = sql;
foreach (var parameter in parameters)
{
if (parameter != null)
command.Parameters.Add(parameter);
}
connection.Open();
return command.ExecuteNonQuery();
}
}
}
catch (Exception)
{
throw;
}
}
You will want to strip all ', ", and ` characters out of your input so that people can't inject SQL. When you do SET Name = " +, you'll want to actually wrap whatever you're including in quotes because it's a string: SET Name = '" + UserName "' " +...
This is probably best done using
string.Format("UPDATE UserLogin SET Name = '{0}' WHERE Name = '{1}'", UserName, FormerUserName);
Then you will execute your query by using System.Data.SqlClient; and then work with SqlConnection to establish a connection to the server, and execute a SqlCommand of some kind; take a look at: http://www.codeproject.com/Articles/4416/Beginners-guide-to-accessing-SQL-Server-through-C
The following is a code snippet to insert data into database using ADO.NET and assuming SQL Server database.
At the top of your .cs file you should have.
using System.Data.SqlClient; // for sql server for other data bases you should use OleClient instead.
And inside your button click event you could put the following.
// to know how to get the right connection string please check this site: http://www.connectionstrings.com
string connString = "database connection string here";
using (SqlConnection con = new SqlConnection(connString))
{
con.Open();
//insert text into db
string sql_insert = "INSERT INTO ....."; // Use parameters here.
SqlCommand cmd_insert = new SqlCommand(sql_insert, con);
int rowsAffected = cmd_insert.ExecuteNonQuery();
}
Hopefully this is enough to get you started.
This is my simple Code which stores parameters value in variables and use it on query
but it's give me ERROR message "INVALID Object name "DTA010.DFDR00" because I guess i'm not connected with the AS/400
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//string strQuery;
string order_no = Request.QueryString["order"];
if (order_no != null)
{
Response.Write("\n");
Response.Write("Order No is ");
Response.Write(order_no);
}
else
{
Response.Write("You Order number is not correct");
}
Response.Write("Your Order Status is");
Response.Write(niceMethod1());
Response.Write("\n");
}
public string niceMethod1()
{
string tDate = "";
string nOrder = (Request.QueryString["order"] ?? "0").ToString();
using (SqlConnection connection = new SqlConnection("Data Source=*****;User ID=web;Password=****;Initial Catalog=WEBSTATUS;Integrated Security=False;"))
{
string commandtext = "SELECT A.STAT01 FROM DTA010.DFDR00 AS A WHERE A.ORDE01 = #nOrder"; //#nOrder Is a parameter
SqlCommand command = new SqlCommand(commandtext, connection);
//command.Parameters.AddWithValue("#nPhone", nPhone); //Adds the ID we got before to the SQL command
command.Parameters.AddWithValue("#nOrder", nOrder);
connection.Open();
tDate = (string)command.ExecuteScalar();
} //Connection will automaticly get Closed becuase of "using";
return tDate;
}
}
The drivers needed to connect from a .NET application to a AS/400 are properly installed.
If the names of the schema (aka library) and table (aka file) are spelled correctly, try replacing the period with a slash /. This would be used for "system" naming syntax, rather than "standard" naming syntax.
You are definitely connected. I think the issue may be in the error you received. Make sure that the object exists that you are connecting to. WRKOBJ OBJ(BTGDTA010/DF01HDR00) will see if it exists. Check that everything is spelled right. It might be a typo.
Here is the simplest way I Found may be useful for someone..!!
First need to add Assembly IBM library and
using IBM.Data.DB2.iSeries;
then
iDB2Connection connDB2 = new iDB2Connection(
"DataSource=158.7.1.78;" +
"userid=*****;password=*****;DefaultCollection=MYTEST;");