I'm trying to select values to a MySQL table.
I use the AddWithValue method, but it doesn't substitute what I have in the command string.
Here is some sample code that fails and the return is empty.
private DataSet RetrieveProducts()
{
DataTable dt1 = new DataTable();
DataTable dtProducts = new DataTable();
DataSet dsProducts = new DataSet();
var paramValuenamens = string.Join(", ", Masterpage.Container.TheObjectPropertyNameNs);
var strEmail = Masterpage.Container.TheObjectPropertyNameEmail.ToString();
string sql = #String.Format(" SELECT * FROM ");
sql += String.Format(" doTable ");
sql += String.Format(" WHERE 1 ");
if (Masterpage.Container.theObjectPropertyAut == 1)
{
sql += String.Format(" AND doTableEmail = ? ");
}
sql += String.Format(" AND doTableNameNs IN ({0}) ", paramValuenamens.ToString());
using (MySqlConnection myConnectionString =
new MySqlConnection(ConfigurationManager.ConnectionStrings["cn"].ConnectionString))
{
using (MySqlCommand cmd =
new MySqlCommand(sql, myConnectionString))
{
cmd.Parameters.AddWithValue("param1", strEmail.ToString());
foreach (var param in paramValuenamens)
{
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("param2", param.ToString());
}
MySqlDataAdapter adapter =
new MySqlDataAdapter(cmd);
adapter.Fill(dsProducts);
if (dsProducts.Tables.Count > 0)
{
dt1 = dsProducts.Tables[0];
}
dtProducts = dt1;
}
}
return dsProducts;
}
But if change my code from
if (Masterpage.Container.theObjectPropertyAut == 1)
{
sql += String.Format(" AND doTableEmail = ? ");
}
To
if (Masterpage.Container.theObjectPropertyAut == 1)
{
sql += String.Format(" AND doTableEmail = '" + strEmail.ToString() + "' ");
}
The return is correct...
I have tried this suggestion without success
How to do resolve this?
Can you help me, please?
Thank you in advance for any help
You are trying to use parameters without setting the proper placeholder in the query text.
So change the condition to....
if (Masterpage.Container.theObjectPropertyAut == 1)
{
sql += " AND doTableEmail = #email ");
}
....
Now add the parameter using the same name used for the placeholder
cmd.Parameters.AddWithValue("#email", strEmail);
Then you have a useless loop that clear the parameter collection at each loop.
You don't need it because you have already added the values directly through the string format above.
// foreach (var param in paramValuenamens)
// {
// cmd.Parameters.Clear();
// cmd.Parameters.AddWithValue("param2", param.ToString());
// }
Now this should work, but of course, this is not a complete parameterized query because the IN clause for the doTableNameNs still uses a string concatenation (Format is still a concatenation and doesn't keep you safe from sql injection). This is acceptable only if you are absolutely sure that the value used don't come from user input or other media that you cannot control. Otherwise you need to create a collection of parameters and strings placeholders to insert in the IN statement for doTableNameNs
Related
I am very new to database queries and even more so, Oracle. I am also new to development work and, believe it or not, am creating this an for work purely out of frustration with the current process. Anyway, I am attempting to collect input from a multi-line text box and run a query. Each line corresponds to a single string that needs to be passed into the WHERE statement and the results will be dumped into a data table. Unfortunately, Oracle has still not released its developer tools for VS2019 so I am having to do this the harder way.
UPDATE # 2:
I have completely rebuilt the query since it was not running even when using known working code from another query. Below is what I have pieced together from various places on the interwebs. While debugging, it appears to parse and format the text correctly and pass it into the OracleParameter without issue. I am getting a Missing Expression error but I don't know what I am missing.
var connString =
ConfigurationManager.ConnectionStrings["dB"].ConnectionString;
string query = "SELECT col1, col2, col3, col4 FROM table WHERE col5 IN (";
using (OracleConnection conn = new OracleConnection(connString))
try
{
var input = "";
input = uniLookup.UniList;
var uniList = string.Join(",", Regex.Split(input, #"(?:\r\n|\n|\r)"));
string allParams = uniList;
string formattedParams = allParams.Replace(" ", string.Empty);
string[] splitParams = formattedParams.Split(',');
List<OracleParameter> parameters = new List<OracleParameter>();
using (OracleCommand cmd = new OracleCommand(query, conn))
{
for (int i = 0; i < splitParams.Length; i++)
{
query += #":Uni" + i + ",";
parameters.Add(new OracleParameter(":Uni" + i, splitParams[i]));
{
query = query.Substring(0, (query.Length - 1));
query += ')';
conn.Open();
using (OracleDataReader reader = cmd.ExecuteReader()) <==ERROR
{
if (!reader.HasRows)
{
while (reader.Read())
{
reader.Read();
{
MessageBox.Show(reader.GetString(1));
}
}
}
You can use IN in your where clause in this way to get rows from multiple values as:
string query = "SELECT dummyCol FROM dummytable WHERE altCol IN ("+text+");";
where you just have to change your text as text="'value1','value2','value3'"; this will not produce any syntax error.
You can convert your multi line text into same comma separated values using this :
foreach (String s in textBox1.Text.Split('\n'))
{
text +="'"+ s+"',";
}
text = text.TrimEnd(',');
this will help you achieve what you need. you can ask If there is any confusion.
Your final code will become :
public void GetData()
{
if (string.IsNullOrWhiteSpace(textbox1.Text) || textbox1.Text == "")
{
MessageBox.Show("Please Enter at least 1 Value and Try Again!");
}
else
{
System.Data.DataTable dt = new System.Data.DataTable();
// string[] lines = textbox1.Text.Split('\n');
string text = "";
foreach (String s in textBox1.Text.Split('\n'))
{
text += "'" + s + "',";
}
text = text.TrimEnd(',');
//Connection Credentials
string credentials = "Credentials";
string query = "SELECT dummyCol FROM dummytable WHERE altCol IN ("+text+");";
OracleConnection conn = new OracleConnection(credentials);
try
{
//Open The Connection
conn.Open();
using (OracleCommand cmd = new OracleCommand(query, conn))
{
//Call the Oracle Reader
using (OracleDataReader reader = cmd.ExecuteReader())
{
if (!reader.HasRows)
{
MessageBox.Show("Unable to Retrieve Data");
return;
}
else if (reader.HasRows)
{
reader.Read();
DataRow row = dt.NewRow();
// create variables to accept reader data for each column
// insert data from query into each column here
dt.Rows.Add(row);
}
}
}
}
}
}
I want to execute this command
select * from table1 where id='"+comboBox1.Text+"'and name='"+comboBox2.Text+"'
but I don't want them to be considered if they were empty, for example if combobox1.Text is empty, I want the command to be like
select * from table1 where name='"+comboBox2.Text+"'
You can have a check with the text boxes like
if (comboBox1.Text.Trim().Length == 0) {
// your query
}
else{
// other query
}
But you should be using parameterised queries. Building up your queries like that leaves you open to SQL injection.
So your SQL String should be
select * from table1 where id=#id and name=#name
And you add the parameters to the command object before executing the query.
You can build up your query as you go, and still protect yourself from SQL injection:
(I'm writing this from memory, it should compile...)
using (var conn = new SqlConnection("..."))
{
var sb = new StringBuilder("SELECT * FROM table1 WHERE");
using (var cmd = new SqlCommand { Connection = conn })
{
if (!String.IsNullOrEmpty(comboBox1.Text))
{
sb.Append(" id = #ID");
cmd.Parameters.AddWithValue("#ID", int.Parse(comboBox1.Text));
}
if (!String.IsNullOrEmpty(comboBox2.Text))
{
sb.Append(" name = #NAME");
cmd.Parameters.AddWithValue("#NAME", comboBox2.Text);
}
var query = sb.ToString();
cmd.CommandText = query.EndsWith("WHERE") ? query.Remove(query.Length - 5) : query;
conn.Open();
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// do whatever you need to do with your data
}
}
}
}
Something to keep in mind...
This could get out of hand if you have a dozen if blocks instead of just two, and then start nesting more if blocks inside of those. Maintenance will become a nightmare.
It may just be easier, if you only have a few conditions, to just create a few separate queries and determine which one is called instead of building a query dynamically like this.
i found the solution i want
MySqlDataAdapter cmd = new MySqlDataAdapter("select * from table1 where (ID=#id or #id2) and (name=#name or #name2) ", co);
if (comboBox1.Text == "")
{
cmd.SelectCommand.Parameters.AddWithValue("#id", "1");
cmd.SelectCommand.Parameters.AddWithValue("#id2", "1");
}
else
{
cmd.SelectCommand.Parameters.AddWithValue("#id", comboBox1.Text);
cmd.SelectCommand.Parameters.AddWithValue("#id2", "0");
}
if (comboBox2.Text == "")
{
cmd.SelectCommand.Parameters.AddWithValue("#name", "1");
cmd.SelectCommand.Parameters.AddWithValue("#name2", "1");
}
else
{
cmd.SelectCommand.Parameters.AddWithValue("#name", comboBox1.Text);
cmd.SelectCommand.Parameters.AddWithValue("#name2", "0");
}
//thanks everyone for the help , i used all what u gave me to create this solution
I'm trying to implement date-picker functionality in my project, but I can't do it quite right. I'm trying to pass the date-picker value in my oracle string so that it will compare with my db column and return results on the date criteria...
Whenever I pass it to the select statement it won't generate errors particularly but on button click it doesn't perform anything except it shows "not connected".
str = "Select * from sania.doctor where APPOINTMENT_DATE = "+ datepicker1.value;
It is clear it is logical mistake but I'm new to this C# concepts I need someone to tell me how to pass it and then display the results as well.
private void button1_Click(object sender, EventArgs e)
try
{
OracleCommand com;
OracleDataAdapter oda;
string ConString = "Data Source=XE;User Id=system;Password=sania;";
OracleConnection con = new OracleConnection(ConString);
{
// string id = dateTimePicker1.Text.Trim();
con.Open();
// str = "Select * from sania.doctor where APPOINTMENT_DATE = " + dateTimePicker1.value;
str = "select * from sania.doctor where APPOINTMENT_DATE to_date('"+dateTimePicker1.Value.ToString("yyyyMMdd") + "', 'yyyymmdd')";
com = new OracleCommand(str);
oda = new OracleDataAdapter(com.CommandText, con);
dt = new DataTable();
oda.Fill(dt);
Rowcount = dt.Rows.Count;
//int val = 0;
for (int i = 0; i < Rowcount; i++)
{
dt.Rows[i]["APPOINTMENT_DATE"].ToString();
//if (id == dateTimePicker1.Value)// this LINE SHOWS ERROR--because it is a string and I am using date with it. Don't know conversion
// {
// val = 1;
//}
}
// if (val == 0)
// { MessageBox.Show("INVALID ID"); }
// else
// {
DataSet ds = new DataSet();
oda.Fill(ds);
if (ds.Tables.Count > 0)
{
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
else { MessageBox.Show("NO RECORDS FOUND"); }
}
}
//}
catch (Exception)
{ MessageBox.Show("not connected"); }
}
Do not put values into SQL directly, use bind variables/parametes instead. For Oracle:
// :prm_Appointment_Date bind variable declared within the query
String str =
#"select *
from sania.doctor
where Appointment_Date = :prm_Appointment_Date";
....
using(OracleCommand q = new OracleCommand(MyConnection)) {
q.CommandText = str;
// datepicker1.Value passed into :prm_Appointment_Date via parameter
q.Parameters.Add(":prm_Appointment_Date", datepicker1.Value);
...
}
Doing like that you can be safe from either SQL Injection or Format/Culture differences
I want to get the names associated with the states i select in my program. Below is the code that i currently have. My database has multiple locations within a state that have different contacts. I just want to select a state and acquire everyone under that state. Thanks for the help!
con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\\Database\\LocNo.accdb");
con.Open();
foreach (Object c in checkedListBox2.CheckedItems)
{
if (checkedListBox2.GetItemCheckState(checkedListBox2.Items.IndexOf(c)) == CheckState.Checked)
{
str1 += c.ToString() + ",";
flag = 1;
}
}
i = 0;
allSelectedtypestring = "";
allSelected = str1.Split(',');
while (allSelected.Length - 1 > i)
{
str = "select c1 from table where state ='" + allSelected[i++] + "'";
cmd = new OleDbCommand(str, con);
dr = cmd.ExecuteReader();
dr.Read();
allSelectedtypestring += dr.GetString(11);
}
label30.Text = Convert.ToString(allSelectedtypestring);
con.Close();
You can use the following code to retrieve the contacts:
var states = new List<string>();
foreach (Object c in checkedListBox2.CheckedItems)
{
states.Add(c.ToString());
flag = 1; // Can also be substituted by states.Count > 0
}
using(var con = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=F:\\Database\\LocNo.accdb"))
{
con.Open();
using(var cmd = con.CreateCommand())
{
var paramIndex = 0;
var paramClause = new System.Text.StringBuilder(100);
foreach(var state in states)
{
if (paramClause.Length > 0)
paramClause.Append(", ");
paramClause.Append("?");
var paramName = "State" + (paramIndex++).ToString();
cmd.Parameters.AddWithValue(paramName, state);
}
var paramsClause = string.Join(", ", cmd.Parameters.
cmd.CommandText = "select distinct c1 from table where state IN (" + paramsClause.ToString() + ")";
using(var rdr = cmd.ExecuteReader())
{
var contacts = new List<string>();
while(rdr.Read())
{
contacts.Add(rdr.GetString(0);
}
label30.Text = string.Join(", ", contacts);
}
}
}
Please note that I've made the following changes:
Added using statements to reliably dispose the connection, command and reader.
Used a List<string> as a more convenient way to collect the selected states.
Added DISTINCT to the SELECT in order to filter duplicate entries.
Used a parameter in the command text in order to avoid SQL injection attacks. Though this way to use a parameter with an IN clause works for SQL Server, I haven't checked whether it also works for an Access database. Let me know in the comments if it doesn't work.
the follwing functions gives me an error:
FillFields("select Housemcode,Name, HP,Rateperhour ,Resource_H_Code FROM House_Machinery where Housemcode like '" + sSearch + "'");
public void FillFields(string sSQL)
{
sCommands.setSqldbCommand(sVariables.sDataSet, sVariables.sSqlDbDataAdapter, sSQL, "House_Machinery");
DataRow sDataRow = sVariables.sDataSet.Tables["House_Machinery"].Rows[0];
txtItemName.Text = sDataRow["Name"].ToString();
txtrate.Text = sDataRow["HP"].ToString();
txtrate.Text = sDataRow["Rateperhour"].ToString();
Variables.StrResourceHeaderCode = sDataRow["Resource_H_Code"].ToString();
}
the error is:
There is no row at position 0.
can any one give an insight on this?
Your query is simply not returning any rows. Try running the SQL query directly in SQL Management Studio to confirm that data is returned.
Incidentally, you can check whether any data is returned at run-time by counting the rows returned:
sCommands.setSqldbCommand(sVariables.sDataSet, sVariables.sSqlDbDataAdapter, sSQL, "House_Machinery");
if(sVariables.sDataSet.Tables["House_Machinery"].Rows.Count == 0)
throw new Exception("No matching rows found");
DataRow sDataRow = sVariables.sDataSet.Tables["House_Machinery"].Rows[0];
1.Just check with Breakpoints if it works well,
2.Does your Sql query working in sql server ? check that it may circle it out.
3.Check your wildcard "%like%",this may have issues.
void somewhereelse()
{
string qry = "select Housemcode,Name, HP,Rateperhour ,Resource_H_Code FROM House_Machinery where Housemcode like '" + sSearch + "'";
filldetails(qry);
}
protected void filldetails(string someqry)
{
Sqlconnection conn = new SqlConnection("Connectionstring");
Datatable dt = new Datatable();
try
{
conn.Open();
SqlDataAdapter dap = new SqlDataAdapter(someqry,conn);
dap.fill(dt);
if(dt.rows.count >0)
{
txtItemName.Text = dt.rows.[0]["Name"].ToString();
txtrate.Text = dt.rows.[0]["HP"].ToString();
txtrate.Text = dt.rows.[0]["Rateperhour"].ToString();
}
}
catch
{
throw;
}
finally
{
if(conn!= null)
{
conn.close();
}
}