C# NpgsqlCommand - AddWithValue is not substituting - c#

So let me first off state that I know there are other questions with the same issue--I've read most of them and tried different things... Nothing worked.. So please don't close because of "Duplicate" because those ARE NOT working for me.
I am also using Postgres as my database.
Thanks for assistance in advanced.
public static string RetrieveEntry(string table, string lookup)
{
Console.WriteLine("RetrieveEntry");
if (!IsConnected())
{
return "Request Failed";
}
string str = "No poll were found that contained that info.";
string sqlstring = "SELECT * FROM "+table+" WHERE topic = '#t' OR description LIKE '#d' OR started_by = '#sb'";
NpgsqlCommand sql = new NpgsqlCommand(sqlstring,conn);
sql.Parameters.AddWithValue("#t", lookup);
sql.Parameters.AddWithValue("#d", "%" + lookup + "%");
sql.Parameters.AddWithValue("#sb", lookup);
NpgsqlDataAdapter adap = new NpgsqlDataAdapter(sqlstring,conn);
DataSet ds = new DataSet();
adap.Fill(ds);
Console.WriteLine("Table: "+ds.Tables[0].TableName+"; Tables: "+ds.Tables.Count+"; Rows: "+ds.Tables[0].Rows.Count);
if (ds.Tables[0].Rows.Count > 0) str = ""; //Remove default string
foreach (DataRow dr in ds.Tables[0].Rows)
{
str += "Topic:\t" + dr["topic"] +
"\nDesc:\t" + dr["description"].ToString().Substring(0, Math.Min(25, dr["description"].ToString().Length)) + "\n\n";
}
return str;
}

Would using a reader fix the issue?
ds.Load(NpgsqlDataReader reader = sql.ExecuteReader(CommandBehavior.CloseConnection));
from this answer

I know it's a bit late, but I really think You shouldn't use the # character in the AddWithValue parameter.
Something like:
sql.Parameters.AddWithValue("t", lookup);
sql.Parameters.AddWithValue("d", "%" + lookup + "%");
sql.Parameters.AddWithValue("sb", lookup);

Related

MySQL Parameters.AddWithValue fails/not working in c#

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

C# get many rows in one line

in C# I'm currently getting some data from SQL, my query returns me only one column due to my select (see code below) but in some case, it could be possible that I have more than one row, so I'd like to know if is there a way to return these row in only one line of text?
Here my current code:
public bool getDBValue(string m_strValue, string m_strFilter, string m_strDBTable, out DataSet m_objDs, out string m_strError)
try
{
using (SqlConnection oConn = new SqlConnection(getConnectionString()))
{
oConn.Open();
SqlDataAdapter l_objAdapter = new SqlDataAdapter("Select [" + m_strValue + "] FROM "+ m_strDBTable+" Where ProjectUID =" + "'" + m_strFilter + "'", oConn);
m_objDs = new DataSet();
l_objAdapter.Fill(m_objDs);
}
return (true);
}
catch (Exception e)
{
m_strError = e.Message;
return (false);
}
Because for the moment, I used my data with with line:
string value = l_objDs.Tables[0].Rows[0]["ColumnName"].ToString();
but as I could have many values, it returns only one values. So any idea of how could I do that?
Thanks.
No it is not possible since you have taking value at Row[0] of Table[0] so you will get value of first row of your first Table.
string value = l_objDs.Tables[0].Rows[0]["ColumnName"].ToString();
i would rather suggest you to iterate over table rows and add it to a StringBuilder and then assign it to the string value.
Something like Below.
StringBuilder sb = new StringBuilder();
foreach (DataRow dr in l_objDs.Tables[0].Rows)
{
sb.Append(dr["ColumnName"]);
}
string value= sb.ToString();
Hope This Helps!
Just use foreach to loop through all rows:
string value = "";
foreach (DataRow row in m_objDs.Tables[0].Rows)
value += row["ColumnName"];

Condition statements for a single row data value in a database

I am using C# to create a windows form.
I am trying to set a condition statement for a particular value that is retrieved from my database by the onclick of a button. The datatype of the column is 'integer'.
Below is my code:
string checkquantity = "SELECT `inventory_item`.`Item_Quantity_Available`FROM `inventory_item` , `patient`, `out_treatment`WHERE `inventory_item`.`Item_ID` = `out_treatment`.`Inventory_ID`AND `patient`.`Patient_ID` = `out_treatment`.`Patient_ID`AND `out_treatment`.`Patient_ID`= '" + pid + "' ";
MySqlCommand selectout = new MySqlCommand(checkquantity, connect);
MySqlDataAdapter selectdata = new MySqlDataAdapter(checkquantity, connect);
DataTable selecttable = new DataTable();
selectdata.Fill(selecttable);
DataSet ds = new DataSet();
selectdata.Fill(selecttable);
selectdata.Fill(ds);
int i = ds.Tables[0].Rows.Count;
if ( i <= 0)
{
MessageBox.Show("Out of Stock");
}
I'm new with c#.
I don't think the int i = ds.Tables[0].Rows.Count; is the right way.
Any help is much appreciated.
First of all, like #Flydog57 said, you should not concatenate your sql query. The best way is to use parameters, for example:
string checkquantity = "SELECT i.Item_Quantity_Available " +
" FROM inventory_item i JOIN out_treatment t ON i.Item_Id = t.Inventory_ID " +
" JOIN patient p ON t.Patient_ID = p.PatiendID " +
" WHERE t.Patient_ID = #Patiend_ID";
MySqlCommand selectout = new MySqlCommand(checkquantity, connect);
// set the parameter value
selectout.Parameters.AddWithValue("#Patiend_ID", patient_id_value);
MySqlDataReader rdr = cmd.ExecuteReader();
if (rdr.Read())
{
if ((int)rdr["Item_Quantity_Available"] == 0)
MessageBox.Show("Out of Stock");
}
In second place, you could use a MySqlDataReader to verify that Item_Quantity_Available is equal to 0, like in the previous example. Otherwise, If you just wants to verify if there is data, the condition could be something like that:
if (!rdr.Read())
{
MessageBox.Show("Out of Stock");
}
The third improvemente is to join tables with the join clause.

How to retrieve all fields for a given record using OracleDataReader?

My question, which is similar to this one, is how can I use OracleDataReader to retrieve all the fields for a given record? Currently, I've been using this method, which returns only one column value at a time:
public string Select_File(string filename, string subdirectory, string envID)
{
Data_Access da = new Data_Access();
OracleConnection conn = da.openDB();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename ='" + filename + "'"
+ " AND Subdirectory = '" + subdirectory + "'"
+ " AND Environment_ID = '" + envID + "'";
cmd.CommandType = CommandType.Text;
string x;
OracleDataReader dr = cmd.ExecuteReader();
if (dr.HasRows) // file exists in DB
{
dr.Read();
x = dr.GetString(2).ToString(); // return baseline filename (index 2)
}
else
{
x = "New File";
}
cmd.Dispose();
da.CloseDB(conn);
return x;
}
I'm sure that this method is far from perfect and ppl will be quick to point that out (I was basically given it by my supervisor since I didn't have any prior experience in ASP.NET) but all I really care about is that it works. My question is: how can it be modified to return all the fields for a given record?
The fields will be of either VARCHAR2, CHAR, or DATE datatypes, (if that makes a difference) and some of these values may be null. I'm thinking I could convert them to strings and return them as a list?
if u want something like this:
List<User> lstUser = new List<User>();
string sqlQuery = "Select * from User_T where User_Name='" + oUser.UserName + "' And Password='" +oUser.Password + "' AND IsActive='"+1+"' AND IsDelete='"+0+"'";
string connectionString = "Data Source=ORCL;User Id=ACCOUNTS;Password=ACCOUNTS";
using (DBManager dbManager = new DBManager(connectionString))
{
try
{
dbManager.Open();
OracleDataReader dataReader = dbManager.ExecuteDataReader(sqlQuery);
while (dataReader.Read())
{
oUser = new User();
oUser.Id = Convert.ToInt32(dataReader["ID"]);
oUser.CompanyId = Convert.ToInt32(dataReader["Company_ID"]);
oUser.BranchId = Convert.ToInt32(dataReader["Branch_ID"]);
oUser.UserName = Convert.ToString(dataReader["User_Name"]);
lstUser.Add(oUser);
}
dataReader.Close();
dataReader.Dispose();
}
catch
(Exception)
{
}
finally
{
dbManager.Close();
dbManager.Dispose();
}
To read all the data from the columns of the current row in a DataReader, you can simply use GetValues(), and extract the values from the array - they will be Objects, of database types.
Object[] values;
int numColumns = dr.GetValues(values); //after "reading" a row
for (int i = 0; i < numColumns; i++) {
//read values[i]
}
MSDN - "For most applications, the GetValues method provides an efficient means for retrieving all columns, rather than retrieving each column individually."
Sorry for posting an answer to a very old question. As none of the answers are correct (either they have security issues or not checking for DBNull), I have decided to post my own.
public async Task<StringBuilder> FetchFileDetailsAsync(string filename, string subdirectory, string envId)
{
var sb = new StringBuilder();
//TODO: Check the parameters
const string connectionString = "user id=userid;password=secret;data source=" +
"(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=10.0.0.8)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=xe)))";
const string selectQuery = "SELECT * FROM EIP_Deployment_Files"
+ " WHERE Filename = :filename"
+ " AND Subdirectory = :subdirectory"
+ " AND Environment_ID = :envID"
+ " AND rownum<=1";
using (var connection = new OracleConnection(connectionString))
using (var cmd = new OracleCommand(selectQuery, connection) {BindByName = true, FetchSize = 1 /*As we are expecting only one record*/})
{
cmd.Parameters.Add(":filename", OracleDbType.Varchar2).Value = filename;
cmd.Parameters.Add(":subdirectory", OracleDbType.Varchar2).Value = subdirectory;
cmd.Parameters.Add(":envID", OracleDbType.Varchar2).Value = envId;
//TODO: Add Exception Handling
await connection.OpenAsync();
var dataReader = await cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection);
var rowValues = new object[dataReader.FieldCount];
if (dataReader.Read())
{
dataReader.GetValues(rowValues);
for (var keyValueCounter = 0; keyValueCounter < rowValues.Length; keyValueCounter++)
{
sb.AppendFormat("{0}:{1}", dataReader.GetName(keyValueCounter),
rowValues[keyValueCounter] is DBNull ? string.Empty : rowValues[keyValueCounter])
.AppendLine();
}
}
else
{
//No records found, do something here
}
dataReader.Close();
dataReader.Dispose();
}
return sb;
}

spliting large query string in acess

I had a long query in access and trying to make it into multiple lines so that i can check them during my debugging and I tried the steps which I found through google and its failing with the information shown below.
public DataSet showallCompanyPaymentbyjobcode(int jobpk ,int confirmquotationpk)
{
string query=SELECT companypaymentmastertable.paymentpk, companypaymentmastertable.cmpinvoice, companypaymentmastertable.jobcode, companypaymentmastertable.customercode, confirmquotationmastertable.quotationcode, companypaymentmastertable.customerName, companypaymentmastertable.ischeque, companypaymentmastertable.isCash, companypaymentmastertable.amount, companypaymentmastertable.chequenumber, companypaymentmastertable.bankname, companypaymentmastertable.chequedate, companypaymentmastertable.chequereleasedate, companypaymentmastertable.companypaymentdate
FROM confirmquotationmastertable INNER JOIN companypaymentmastertable ON confirmquotationmastertable.confirmpk=companypaymentmastertable.confirmpk
WHERE (((companypaymentmastertable.confirmpk)=[?]) AND ((companypaymentmastertable.jobpk)=15));
OleDbDataAdapter dAdapter = new OleDbDataAdapter(query, Program.ConnStr);
DataSet ds = new DataSet();
dAdapter.Fill(ds, "tblpayview");
if (ds.Tables.Count <= 0)
{
ds = null;
}
return ds;
}
in another class i called it
public void fillpaymenttable()
{
DataSet ds= new DataSet();
ds= companytransaction.showallCompanyPaymentbyjobcode(cmbjobcode.SelectedValue,cmbQuotationcode.SelectedValue);
tblpaymentview.DataSource = ds.Tables["tblpayview"].DefaultView;
if (ds.Tables.Count <= 0)
{
lblstatus.Text = "No Payment Details Present";
clearcontrols();
}
}
Is there any way to split the query and whether this function work if dataset called like this?
If you're just wanting to actually split the code up into separate lines, use a StringBuilder? Note that this wouldn't be the case if you were passing parameters to the query as you'd be vulnerable to SQL injections
var query = new StringBuilder();
query.Append("SELECT companypaymentmastertable.paymentpk, companypaymentmastertable.cmpinvoice, ");
query.Append("companypaymentmastertable.jobcode, companypaymentmastertable.customercode, ");
query.Append("confirmquotationmastertable.quotationcode, companypaymentmastertable.customerName, ");
query.Append("companypaymentmastertable.ischeque, companypaymentmastertable.isCash, ");
query.Append("companypaymentmastertable.amount, companypaymentmastertable.chequenumber, ");
query.Append("companypaymentmastertable.bankname, companypaymentmastertable.chequedate, ");
query.Append(" companypaymentmastertable.chequereleasedate, companypaymentmastertable.companypaymentdate ");
query.Append("FROM confirmquotationmastertable INNER JOIN companypaymentmastertable ");
query.Append("ON confirmquotationmastertable.confirmpk=companypaymentmastertable.confirmpk ");
query.Append("WHERE (((companypaymentmastertable.confirmpk)=[?]) ");
query.Append("AND ((companypaymentmastertable.jobpk)=15))");
This would be more efficient than using a stringbuilder, because the string concatenation will be performed at compile time, not at run time:
string query="SELECT companypaymentmastertable.paymentpk, companypaymentmastertable.cmpinvoice, "
+ "companypaymentmastertable.jobcode, companypaymentmastertable.customercode, "
+ "confirmquotationmastertable.quotationcode, companypaymentmastertable.customerName, "
+ "companypaymentmastertable.ischeque, companypaymentmastertable.isCash, companypaymentmastertable.amount, "
+ "companypaymentmastertable.chequenumber, companypaymentmastertable.bankname, companypaymentmastertable.chequedate, "
+ "companypaymentmastertable.chequereleasedate, companypaymentmastertable.companypaymentdate "
+ "FROM confirmquotationmastertable INNER JOIN companypaymentmastertable ON "
+ "confirmquotationmastertable.confirmpk=companypaymentmastertable.confirmpk "
+ "WHERE (((companypaymentmastertable.confirmpk)=[?]) AND ((companypaymentmastertable.jobpk)=15));"
Alternatively, you could use a "verbatim string":
string query= #"SELECT companypaymentmastertable.paymentpk, companypaymentmastertable.cmpinvoice,
companypaymentmastertable.jobcode, companypaymentmastertable.customercode,
confirmquotationmastertable.quotationcode, companypaymentmastertable.customerName,
companypaymentmastertable.ischeque, companypaymentmastertable.isCash, companypaymentmastertable.amount,
companypaymentmastertable.chequenumber, companypaymentmastertable.bankname, companypaymentmastertable.chequedate,
companypaymentmastertable.chequereleasedate, companypaymentmastertable.companypaymentdate
FROM confirmquotationmastertable
INNER JOIN companypaymentmastertable ON confirmquotationmastertable.confirmpk=companypaymentmastertable.confirmpk
WHERE (((companypaymentmastertable.confirmpk)=[?]) AND ((companypaymentmastertable.jobpk)=15));";

Categories

Resources