C# - How to parametrize SQL query with MySqlAdapter - c#

I'm trying to run a SQL query using MySqlAdapter so it returns the data in a DataTable.
I'm having troubles with the parametrization. Basically it doesn't return anything and it should be returning 2 rows.
I have this code:
using (MySqlConnection connection = new MySqlConnection(CONSTANTS.dbCONNECTSTRING))
{
string sqlQuery = $"SELECT * FROM tfg_bcovi.User where userName= '#userName'";
MySqlCommand command = new MySqlCommand(sqlQuery, connection);
command.Parameters.Add(new MySqlParameter("#userName", userCtrl.UserName));
MySqlDataAdapter dataAdapter = new MySqlDataAdapter(command);
DataSet dataSet = new DataSet();
dataAdapter.Fill(dataSet);
DataTable dtResults = dataSet.Tables[0];
}
I checked and userCtrl.UserName have the correct value so I'm asuming something is wrong with parametrization.
The problem as I said before, is that dtResults ends up empty when it whould have at least 2 rows. I checked running the query in SQL.
What am I doing wrong?
Thanks!

Just remove the single quotes around the parameter. Your drive handles that for you already.
This:
string sqlQuery = $"SELECT * FROM tfg_bcovi.User where userName= '#userName'";
Should be:
string sqlQuery = $"SELECT * FROM tfg_bcovi.User where userName= #userName";

Related

ASP.NET getting data from SQL Server

I am trying to get the name of the employee from the database and fill it in the textbox for the respective employee id.
I tried this code but nothing is happening on the page. It just reloads and the textbox (name) is left blank only.
SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-0FUUV7B\SQLEXPRESS;Initial Catalog=EmployeeDetails;Integrated Security=True");
con.Open();
           
SqlCommand cmd = new SqlCommand("select * from ProfessionalDetails where EmpId='"+EmployeeId.Text+"'", con);
          
SqlDataReader da = cmd.ExecuteReader();
while (da.Read())
{
    Name.Text = da.GetValue(1).ToString();
}
            
con.Close();
Better solution is to execute the sql statement through Parameterized value.
The details of that process is given below:
using (SqlConnection con = new SqlConnection(live_connectionString))
{
using (SqlCommand cmd = new SqlCommand("Query", con))
{
con.Open();
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#EmpId", employeeId);
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
var ds = new DataSet();
da.Fill(ds);
string? name = ds.Tables[0].Rows[1]["Variable name"].ToString();
Name.Text =name;
};
}
}
As mentioned above in comments, you have lot of issues.
you should use using with the connection to dispose of them.
You should use parameterized queries to avoid SQL injection.
Put your code in try catch so that you can easily identify the root cause of the issue.
Define the connection string in config file three than defining in the c# code.
You don’t need to select all the columns. And please avoid select * in the query, instead just write your column name, as you want to select only one column here.
You can use ExecuteScalar, it’s used when you are expecting single value.
And first make sure that textbox has the expected value when you are calling this query.
As noted, use paramters, and BETTER use STRONG typed paramters.
And no need to use a dataset, this is a single table - so use a datatable.
thus:
string strSQL =
#"select * from ProfessionalDetails where EmpId= #ID";
using (SqlConnection con = new SqlConnection(Properties.Settings.Default.TEST4))
{
using (SqlCommand cmd = new SqlCommand(strSQL, con))
{
con.Open();
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = EmployeeID.Text;
DataTable rstData = new DataTable();
rstData.Load(cmd.ExecuteReader());
if (rstData.Rows.Count > 0)
Name.Text = rstData.Rows[0]["Name"].ToString();
}
}

How does sanitize the sql parameter

I write these code all are working fine but there is a warning coming that sanitize the sql parameter.
private DataSet ExcelToDataSet(string fileData)
{
DataSet ds = new DataSet();
string connectionString = GetConnectionString(fileData);
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
// Get all Sheets in Excel File
DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
// Loop through all Sheets to get data
foreach (DataRow dr in dtSheet.Rows)
{
string sheetName = dr["TABLE_NAME"].ToString();
if (!sheetName.EndsWith("$"))
continue;
// Get all rows from the Sheet
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
}
cmd = null;
conn.Close();
}
return (ds);
}
I have to sanitize the following line
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
Usually, when writing SQL Statements, you need to use parameters to pass the data from user input into the sql statement, to prevent SQL Injection attacks. That's why you get this warning. However, there is nothing you can do about it since it's impossible to parameterize identifiers in SQL, and you don't need to do it because you are not concatenating user input, and you are not running this query on a database, so even if you could use SQL injection, the worst you can do is corrupt a single file
UPDATE: I did not notice this was a OleDbConnection, the database you are connecting to may not have the same functionality to quote an identifier. I am leaving this answer here in case someone comes across this question and needs the same thing but for a SQL connection.
As the others have said, there is no need to worry about the warning in this case as the data is not coming from user data.
However everyone is wrong about the fact you cannot parameterize an identifier. You need to build the query dynamically server side and use the QUOTENAME function but it is possible.
foreach (DataRow dr in dtSheet.Rows)
{
string sheetName = dr["TABLE_NAME"].ToString();
if (!sheetName.EndsWith("$"))
continue;
// Get all rows from the Sheet
cmd.CommandText = #"
declare #sql nvarchar(114);
set #sql = N'select * from ' + quotename(#sheetname)
exec sp_executesql #sql
";
cmd.Parameters.Clear();
cmd.Parameters.Add("#sheetname", SqlDbType.NVarChar, 100).Value = sheetName;
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
}
This will generate a dynamic query that will safely escape the name of the table.

The value of TIME(2) column is shown with extra precision zeros while the query returns only 2

I am running a simple sql query using the following code. In my query there is a column called duration with type TIME(2). When I run the query normally on my MySQL Workbench the value of duration is correctly shown with only 2 precision points. But when I fill my DataSet using a SqlDataAdapter like the following this value is shown with 6 extra zeros on my DataGridView:
using (IDbConnection conn = dataFactory.GetDbConnection())
{
conn.ConnectionString = Common.Conf.ConnectionString;
MySqlDataAdapter daRunHistory = new MySqlDataAdapter();
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = "SELECT Name,Duration FROM MyTable;";
cmd.Connection = conn;
dsRunHistory = new DataSet();
daRunHistory.SelectCommand = cmd;
conn.Open();
daRunHistory.Fill(dsRunHistory);
conn.Close();
}
And it is not just the DataGridView, the zeros are in my DataSet as well.
I ended up changing my query as follows to format my time:
SELECT Name, TIME_FORMAT(Duration, '%H:%i:%s') AS 'Duration'
FROM MyTable

Parameter not changing in OleDbCommand

This is a simple search page (search.aspx?title=Hello) and I want to query the db for like matches. According to the microsoft docs (http://msdn.microsoft.com/en-us/library/system.data.oledb.oledbparameter.aspx see: Remarks) this is the correct way to do it, but the parameter (?) never gets set to the value of the query string.
string sqlcmd = "SELECT * FROM TableName WHERE Title LIKE ?";
OleDbCommand command = new OleDbCommand(sqlcmd, sqlcon);
OleDbParameter p1 = new OleDbParameter("#p1", OleDbType.WChar);
p1.Value = Request.QueryString["title"];
OleDbDataAdapter da = new OleDbDataAdapter(command);
da.SelectCommand.Parameters.Add(p1);
DataTable dt = new DataTable();
da.Fill(dt);
The parameter never changes to what the query string was, it just executes the query
SELECT * FROM Table WHERE Title LIKE ?
Could you try the following:
"SELECT * FROM Table WHERE Title LIKE #p1"
I think that is the convention when using parameters in ADO.Net command text.
Here is my solution, you need to have single quotes around the question mark for the SQL to work. Complete solution:
sqlcon.Open();
string sqlcmd = "SELECT * FROM TableName WHERE Title LIKE '%?%'";
OleDbCommand command = new OleDbCommand(sqlcmd, sqlcon);
command.Parameters.Add(new OleDbParameter("p1", Request.QueryString["Title"]));
OleDbDataAdapter da = new OleDbDataAdapter(command);
DataTable dt = new DataTable();
da.Fill(dt);

Dynamically passing a value inside a query?

I have two columns syntax and query in my table Table1. Syntax contains data called po and a query called select * from po_pomas_pur_order_hdr where pomas_pono =. I got this query value by using
SqlDataAdapter da = new SqlDataAdapter("select query from Table1 where syntax = '" + textBox1.Text + "'", conn);
And my problem is that I need to dynamically pass another value inside the query which I retrived using dataadapter like this:
SqlDataAdapter da1 = new SqlDataAdapter(da.tostring() +"'"+ textBox1.Text +"'", conn)
The resulting query should be like this:
select * from po_pomas_pur_order_hdr where pomas_pono = '2PO/000002/09-10'
But it is not possible. How to get a query like this? Any suggestion?
SqlDataAdapter is used to fill datasets and datatables. You cannot obtain the result of a query with ToString(). I think you want to use SqlCommand to execute your first query to retrieve the actual query to run from the database like this:
string query = null;
using (var command = new SqlCommand("select query from Table1 where syntax = #Syntax", conn))
{
command.Parameters.AddWithValue("#Syntax", textBox1.Text);
query = command.ExecuteScalar(); // this assumes only one query result is returned
}
Then you can use the data adapter to fill it:
SqlDataAdapter da1 = new SqlDataAdapter(query +"'"+ textBox1.Text +"'", conn);
Although I would suggest to use parameters for that as well.
in this way is more safe: dotnetperls
He check the "'" and the "\", check the type of the fields etc...
Code from the example above (is the same for insert delete and update):
using (SqlCommand command = new SqlCommand("SELECT * FROM Dogs1 WHERE Name LIKE #Name", connection))
{
//
// Add new SqlParameter to the command.
//
command.Parameters.Add(new SqlParameter("Name", dogName));
//
// Read in the SELECT results.
//
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
int weight = reader.GetInt32(0);
string name = reader.GetString(1);
string breed = reader.GetString(2);
Console.WriteLine("Weight = {0}, Name = {1}, Breed = {2}", weight, name, breed);
}
}
I suggest you to use SqlParameters. Here is example how to use DataAdapter and parameters.
Provided that you have a DataSet you intend to fill using the adapter and that you adjust the queries to use parameters in order to avoid sql injection you should be able to use something like this:
string query;
using(var sqlCommand = new SqlCommand(
"select query from Table1 where syntax=#syntax", conn))
{
sqlCommand.Parameters.AddWithValue("syntax", textBox1.Text);
query = (string)sqlCommand.ExecuteScalar();
}
using(var dataAdapter = new SqlDataAdapter())
using(var dataCommand = new SqlCommand(query, conn))
{
dataCommand.Parameters.AddWithValue("parameter", poNumber);
dataAdapter.SelectCommand = dataCommand;
dataAdapter.Fill(myDataSet);
}

Categories