Filtering datatable number column - c#

i would like to filter a datatable by a column which contains number data, i'm trying the following:
string selected = colSelect.GetItemText(colSelect.SelectedItem);
if (filterText.Text.Length == 0)
{
data_table.DefaultView.RowFilter = string.Empty;
}
else
{
data_table.DefaultView.RowFilter = string.Format("Price Like '%{0}%'", filterText.Text);
I've tried casting the second value to a string but no luck, i get the error:
Cannot perform 'Like' operation on System.Decimal and System.String
The data entered would be any number or text, but based on the data only relevant number values would show with the filter.

Looks like Price column is decimal typed but you supplied a string which is filterText.Text to filter it.
One solution might be using CONVERT which is explained in DataColumn.Expression documentation like;
data_table.DefaultView.RowFilter = "CONVERT(Price, 'System.String') like '%" + filterText.Text + "%'";
I didn't tried this one but you can parse your filterText.Text to decimal (if it is valid one) and use it like;
data_table.DefaultView.RowFilter = "Price Like '%" + decimal.Parse(filterText.Text) + "%'";
But as I said, I an not %100 sure for the second one.

Related

System.Data.SyntaxErrorException: 'Syntax error: Missing operand after '=' operator.'

I'm trying to make a search bar that searches in the Access database table with multiple criteria.
When I type in the search bar a number it will do the search just fine, but when I delete what's in the search bar it shows me this error:
System.Data.SyntaxErrorException:
'Syntax error: Missing operand after '=' operator.'
And when I type a character it shows me this error:
'System.Data.EvaluateException: 'Cannot find column [a].'
Note:
the Chamber field is type number, long integer.
Here is the code:
private void ResSearchtextBox_TextChanged(object sender, Eventers e)
{
Data View dv = dt.DefaultView;
dv.RowFilter = "(Name LIKE'%" + ResSearch_textBox.Text + "%') OR (Surname LIKE'%" + ResSearch_textBox.Text + "%') OR (Chamber =" + ResSearch_textBox.Text + ")";
ResDGV.DataSource = dv;
}
What I've tried:
private void ResSearchtextBox_TextChanged(object sender, EventArgs e)
{
DataView dv = dt.DefaultView;
dv.RowFilter = "(Name LIKE'%" + ResSearch_textBox.Text + "%') OR (Surname LIKE'%" + ResSearch_textBox.Text + "%') OR (Chamber ='" + ResSearch_textBox.Text + "')";
ResDGV.DataSource = dv;
}
The issue you're seeing is because the RowFilter property expects a string in the format of an SQL WHERE clause, and you are trying to use it to filter based on the value in the ResSearch_textBox control. When the text box is empty, the RowFilter property is being set to "(Name LIKE'%%') OR (Surname LIKE'%%') OR (Chamber =)", which is causing the error you mentioned. When you type a character in the text box, the RowFilter property is being set to "(Name LIKE'%a%') OR (Surname LIKE'%a%') OR (Chamber ='a')", which is causing the second error you mentioned.
To fix these issues, you can add some logic to your code to handle the case where the text box is empty. One way to do this is to check the length of the text in the text box, and only apply the filter if the length is greater than 0. You can also use the TryParse method to try converting the text in the text box to a number, and only apply the Chamber = filter if the conversion is successful.
If there is no value in ResSearch_textBox, the formatted row filter will be, in part, ...OR (Chamber =) in the first case,and ...OR (Chamber = ''), in the second. The first is invalid SQL, as the error indicates. The second might be a database error, because if the Chamber field is expected to be a number, ’’ can’t be converted to one. The solution depends on what you want to happen if there is no chamber filter. If you don’t want to do the query at all, you could add code to the handler to skip the query if there’s no value. You could also substitute a default value — 0, maybe? — instead of a blank.
The error is pretty clear, then the value of the textbox is empty in that case it becomes something like (Name LIKE'%%') OR (Surname LIKE'%%') OR (Chamber =) and hence there is no value after = that is why you are seeing the Syntax error: Missing operand after '=' operator.' error.
your second error looks related to the datatype.
when you have only an a character in that case RowFilter is trying to compare with the string value but the Chamber datatype is different.
so you should add a check like before this code if (searchText == "" || add other checks here) { return; }

C# - SQL Query Rounding Problem while adding DataGridView

I have an SQL query and it has comma value. When I adding it to DataGridView I want to this format (#, ##). I tried Math.Round() function but it doesn't work.
Below is the query I have tried:
(CONVERT(DECIMAL(18, 2), column3)*100) as normalize
It's my C# code for adding;
dgv.Rows.Add(rows["column1"].ToString() + " " + rows["column2"].ToString(), rows["column3"], "%" + "" + Math.Round(Convert.ToSingle(rows["normalize"].ToString())), 2);
It runs without comma with this code. Normally, If I don't use Math.Round it works like this format (#, ####).
And I tried this one also;
dgv.Columns[2].DefaultCellStyle.Format = "N2";
How should I fix it?
Try this, add the value type property, it works on my case.
dgv.Columns[2].DefaultCellStyle.Format = "N2";
dgv.Columns[2].ValueType = typeof(Double);
Full code sample
object[] row = new object[] { 6.54553 };
dataGridView1.Rows.Add(row);
dataGridView1.Columns[0].DefaultCellStyle.Format = "n2";
dataGridView1.Columns[0].ValueType = typeof(double);

Incrementer not working inside string replace

I'm attempting to read a line from a file (csv header) and create a column list that prepends "c[num]_" in front of each column with this code:
int colCount=0;
string line = "col1,col2,col3,col4,col5";
string ColumnList = "([" + (++colCount).ToString() + "_" + line.Replace(",", "],[c" + (++colCount).ToString() + "_") + "]";
I know it's not elegant, but I'm also not sure why my colCount variable doesn't increment inside the replace?? It results with a string like:
([c0_col1],[c1_col2],[c1_col3],[c1_col4],[c1_col5])
The counter increments the first time and then not again inside the replace. Any insights? I think it might be better written with a Regex ReplaceEvaluator but I haven't been able to piece that together yet either.
The paramter of the Replace method is string, and the expression you've entered there is just a string. The count will always be 2. It's not a Func, it a string.
You can use the following Linq to easily achieve the conversion you'd like:
string ColumnList = string.Join(",", line.Split(',').Select((s, i) => $"[c{i + 1}_{s}]"));

Set value and string in datagridview

this question might be very basic. But I just want to make this clear:
lets say I have a code like :
string currentToner = (string)((Hashtable)ht[1])["value"];
string maxToner = (string)((Hashtable)ht[2])["value"];
Now I want to set this value in data grid view.
int number = dataGridView1.Rows.Add();
dataGridView1.Rows[number].Cells[0].Value = currentToner."/".maxToner; //-->this is not the correct way.
How to set the value so that it looks something like:
5000/10000
You are doing it the PHP way, in C# string concatenation is done with plus signs
dataGridView1.Rows[number].Cells[0].Value = currentToner + "/" + maxToner;
You can format the string as well
dataGridView1.Rows[number].Cells[0].Value = string.Format("{0}/{1}", currentToner, maxToner);
If you want to display a string, set a string as the value :
dataGridView1.Rows[number].Cells[0].Value = currentToner + "/" + maxToner;

Generate a string like a WHERE statement by a dictionary

I know we should never do this:
string select = "SELECT * FROM table1 ";
string where = "WHERE Name = '" + name + "' ";
string sql = select + where;
//execute the sql via ADO.NET
because of sql injection, because name can contain the char ', because of another 100 reasons. But now I have to do something similiar. I have a Dictionary<string, object> whose data look like:
Key(string) Value(object)
"Name" "Bob" //string
"ID" 10092L //long
"Birthday" 1980-05-07 00:00:00 //DateTime
"Salary" 5000.5m //decimal
//some others, whose key is a string, and value is string/long/int/DateTime/decimal
I want an easy way, to get all items in the dictionary collected in a String, just like a where statement:
Name = 'Bob' and ID = 10092 and Birthday = '1980-05-07 00:00:00' and Salary = 5000.5
String and DateTime are quoted with ', but note that the Name can be O'Neal. Is there any easy implementation? Input the dictionary, and return the string as a result.
EDIT Note that what I want is the string, I'm not going to execute it, parameterized command doesn't help. I just want a string that looks like a perfect safe WHERE statement.
The first code is only a problem if name is something entered by the user. Otherwise, it should be fine.
I don't know that it eliminates all problems but you might try experimenting with something like name = name.Replace("'", "''"). By converting all single quotes to double single quotes, you prevent the type of problems you described. Another approach might be to remove any single quotes.
However, the best route is to use query arguments. ADO supports these nicely and that would also eliminate any possibility of injection attacks.
The easy way could be like this:
string results = string.Join(" and ", myDict.Select( x=> x.Key + " = " + x.Value));
This of course wouldn't solve the quotes ' issue depending on different datatypes so you cannot use this as input to a SQL query - for that I would strongly recommend named parameters anyway - but is otherwise correct depending on the ToString() implementation of the values in your dictionary.
I wrote this many years ago, and always use it, and never ever have to think about this again. it is a waste of brain cells to solve this more than once:
// replace things like:
// O'Keefe with
// 'O''Keefe'
// make sure you don't call this twice!
static public string SqlString(string strInputSQL)
{
string strOut;
strOut = strInputSQL;
strOut = strOut.Replace ("'", "''");
strOut = "'" + strOut + "'";
return strOut;
}
Use it like this:
string sql = "SELECT * FROM FOO WHERE Name LIKE " + SqlString(myvalue);
There may be a dozen other ways to do it, but if you can have one and only one function, and use it consistently, you will save alot of time.
Try this link : Creating safe SQL statements as Strings
Some people consider this over-engineered, or just labourious to type. I fall back on a simple argument though...
Someone has already invested time and effort ensuring arguements can be safely and reliably included in SQL statements. Are you 100% certain you have pre-empted every possible scenario? Or is it more likely tried and tested code is more reliable?
But, then, I'm a bit anal ;)
var sb = new StringBuilder();
var isFirst = true;
foreach (var element in dic)
{
if(!isFirst)
sb.Append(" AND ");
else
isFirst = false;
sb.Append(element.Key);
sb.Append(" = ");
if(element.Value is decimal)
sb.Append(CastToSqlDecimalString((decimal)element.Value));
else
sb.Append("'" + String.Format(CultureInfo.InvariantCulture, "{0:G}", element.Value).Replace("'", "''") + "'");
}
You might want to handle decimals using this function
public static string CastToSqlDecimalString(decimal dec)
{
var sqlDecimal = new System.Data.SqlTypes.SqlDecimal(dec);
return string.Format("CAST({0} AS DECIMAL({1}, {2}))",
string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0:G}", dec),
sqlDecimal.Precision,
sqlDecimal.Scale);
}

Categories