Exception when making select on datatable - c#

This is my code
var compainNames = (from row in DTgraph.AsEnumerable()
group row by row.Field<string>("Campaign") into grp
select new
{
CampaignName = grp.Key
}).ToList();
var dataForOneCampaint = DTgraph.Select("Campaign = " + compainNames[i].ToString()).ToList();
where DTgraph is a datatable.
I got this exception:
Cannot interpret token '{' at position 12.
Could you help please?
I debug and i can see that compainNames has 3 strings
the exception in this line
var dataForOneCampaint = DTgraph.Select("Campaign = " + compainNames[i].ToString()).ToList();

DataTable.Select method use the same rules with DataColumn.Expression property for creating filters.
From it's documentation;
User-Defined Values
User-defined values may be used within expressions to be compared with
column values. String values should be enclosed within single
quotation marks (and each single quotation character in a string value
has to be escaped by prepending it with another single quotation
character).
I believe you can use;
var dataForOneCampaint = DTgraph
.Select("Campaign = '" + compainNames[i].ToString() + "'")
.ToList();
Or use String.Format as Felipe mentioned.

Try using the ' char between the string, for sample:
var dataForOneCampaint = DTgraph
.Select(string.Format("Campaign = '{0}'", compainNames[i].ToString()))
.ToList();

Related

C# Extension method to Convert into the comma separated [duplicate]

This question already has answers here:
IN Operator in OLEDB
(2 answers)
Closed 1 year ago.
I have some data like name,firstname,surname,std,Rollno.
Using C#, I want to convert this into
('name', 'surname', 'std', 'Rollno')
so that I can use this this data to query into the SQL/MySQL DB like -
SELECT *
FROM Table1
WHERE UserCommunicationId IN ('name', 'surname', 'std', 'Rollno');
Instead of
SELECT *
FROM Table1
WHERE UserCommunicationId IN ('name,surname,std,Rollno');
You can try below below logic
public static class SQLQueryExtensions
{
public static string ColumnFormat(this String str)
{
return "(" + //Include first parenthesis
string.Join(", ", str.Split().Select(x => $"'{x}'")) //Add single quote to each column
+ ")"; //Include last parenthesis
}
}
You can do it in one line as well,
var inputStr = "name,firstname,surname,std,Rollno";
var result = "(" + string.Join(", ", inputStr.Split().Select(x => $"'{x}'")) + ")";
Try Online
Use blow logic, will solve your problem.
string inputStr = "name,firstname,surname,std,Rollno";
string result = string.Join(",", inputStr.Split(',').Select(x => string.Format("'{0}'", x)).ToList());
Output = 'name','firstname','surname','std','Rollno'
One approach I can come up is that:
Set the whole string into query as a parameter.
Split it in a WITH query.
LEFT JOIN it in the main query.
NOT NULL to check if there's any hit.
I've wrote an example below, but I am Oracle user so I am not sure if these syntax are right, not even tested, just googled around. Only take it as an reference to the explanation of the idea.
WITH RECURSIVE targets (stringBuffer, word) AS (
SELECT
#Parameter
,NULL
UNION ALL
SELECT
SUBSTRING(stringBuffer, LEAST(LENGTH(SUBSTRING_INDEX(stringBuffer, ',', 1) + 1, LENGTH(stringBuffer)))
,SUBSTRING_INDEX(stringBuffer, ',', 1)
WHERE LENGTH(word) > 0
OR LENGTH(stringBuffer) > 0 -- I am not really sure about these
)
SELECT *
FROM Table1
LEFT JOIN targets ON targets.word = Table1.UserCommunicationId
WHERE targets.word IS NOT NULL;
Then, in C#, set Parameter for your query command in string like this
string s = "name,firstname,surname,std,Rollno";
Edit:
Or, simply:
SELECT *
FROM Table1
WHERE REGEXP_LIKE(UserCommunicationId, #Parameter)
;
While setting the Parameter in C# as:
string s = "name|firstname|surname|std|Rollno";
Notice that if the keywords can be input by user, you still have the problem where user may enter .+ and it responds every data to them as long as there's no other condition added.
But personally, I think there's a potential issue in your design if you really need an unknown length of IN-CLAUSE in your query. If keywords that can be applied are limited in number, you can, rough but it's my team's current criteria, concat the WHERE section keyword by keyword in C#.

C# String Parameters to protect against injection?

Take this code as an example:
IAmazonSimpleDB client = new AmazonSimpleDBClient(Amazon.RegionEndpoint.USEast1);
SelectResponse response = client.Select(new SelectRequest() {
SelectExpression = "SELECT * FROM `foo` where FooID = '" + id + "'" });
I can rewrite it as such:
IAmazonSimpleDB client = new AmazonSimpleDBClient(Amazon.RegionEndpoint.USEast1);
SelectResponse response = client.Select(new SelectRequest() {
SelectExpression = "SELECT * FROM `foo` where FooID = '{0}'", id });
But from my understanding, that still leaves it vulnerable to injection right?
Is there anything else I can do here? We aren't using SQL so I can't do SQL Parameters.
I usually do a check to see if the id is an integer. That way you will get an exception or a Boolean value if it isn't an int. It will work fine unless you are using GUID values.
var isNumeric = int.TryParse("123", out int n); //Will give a bool
Int32.Parse(yourString); //This will give an exception if it is not an possible integer
If it's anything more than that then you could use a Regex expression to look for strange values and remove characters that shouldn't be there such as spaces. Most SQL injection attacks wont work if there's no spaces... I think. Removing all the spaces is pretty easy and I would assume your ID (even if it is complex) won't include spaces.
string s = " "
string t = s.Replace(" ", ""). //It will be hard to do a sql attack if the spaces are removed.
A little off topic but with C# 6.0 you can format string differentlyl; It's a new feature called "string interpolation" (thanks Etienne de Martel).
$"SELECT * FROM `foo` where FooID = '{id}'"

How use Select with spaced string in C#

How to use this expression correctly with a space in the select query?
string expression = "'Loan' 'ID'='" + ViewState["name"];
DataRow[] sign = ((DataTable)ViewState["customer"]).Select(expression);
I get:
Exception has Operand is missing after ID operator.
This will work and return datarow array.
DataRow[] sign = ((DataTable)ViewState["customer"]).Select("[Loan ID]='" + id_here +"'");

Match the string for different string formating

I have a random .sql file with long sql query. I need to runtime get all table names from the insert sql statement to put into an array. I am able to get the table names (Inventory.tableA) out if the insert statement is in (one line) like the format below:
...
Insert into Inventory.tableA;
...
However, if the Insert statement is in multiple lines like below e.g.
Insert into
Inventory.tableA;
OR
Insert into
(blank line)
(blank line)
Inventory.tableA;
Then my query to retrieve the table name will fail. Can you advise how i can get the table name out from the long sql query which the insert statement can be in either one line or multiple lines? What is the best approach here?
Below is the c# query i tried which can handle for 1 line.
public List<string> GetAllTablesNames(string sp)
{
List<string> output = new List<string>();
string[] contentSplit = sp.Split(new string[] { "INSERT INTO " }, StringSplitOptions.None);
for (int a = 1; a < contentSplit.Length; a++)
{
string[] sa_tableName = contentSplit[a].Substring(0, contentSplit[a].IndexOf("\r")).Trim().Split('.');
output.Add(sa_tableName[0] + "." + sa_tableName[1]);
}
return output.Distinct().ToList();
}
Use singleline mode
List<string> tables= Regex.Matches("yourInput",#"Insert into\s+(.*?)[\s\(]+"
,RegexOptions.Singleline|RegexOptions.IgnoreCase)
.Cast<Match>().Select(x=>x.Groups[1].Value)
.ToList<string>();
//tables contains all the table names
I'm not sure what your regex is, but you could:
Change all spaces in your regex to \s+.
Replace all endlines with " " first, then run it through your regex.
\s will ignore all whitespace, so by using \s+ it will skip over tabs & CRLF. Since your examples had ;, we will capture all text that is not ;. If there is a space between, then use [^;\s]+ instead.
string text = #"Insert into
Inventory.tableA;
Insert into Orders;";
var tableNames = Regex.Matches(text, #"(?:Insert into\s+)(?<Name>[^;]+)(?:;)")
.OfType<Match>()
.Select (mt => mt.Groups["Name"].Value);
Console.WriteLine ("Tables: {0}", string.Join(" ", tableNames));
/* Tables: Inventory.tableA Orders */

How to make addition of two columns data for another column where those two columns are type of string?

I have datatable and there two column which is type of string and I want to make addition of that two columns data for another column how can I do that ?
My column name contains special character and I have used "[" "]" to escaping special character and my columns are type of decimal I am doing
TableExtractedFromFile.Columns[TOT BROK(Rs)].Expression =
"'"+"["+SER TAX(Rs)+"]"+"'+'"+"["+STT(Rs)+"]"+"'";
But The column TOT BROK(Rs) contains the contenation of values of columns SER TAX(Rs) and STT(Rs).But I want the sum of the values of these two columns.
EDIT
It works. But If I do like there is three columns A,B and C. Now if do I table.columns["A"].expression = "A+B+C"; then it gives error like Cannot set Expression property due to circular reference in the expression. then what is the solution of that ?
Use this:
dt.Columns.Add("fullname", typeof(string));
dt.Columns["fullname"].Expression = "lastname + ', ' + firstname";
For adding of value(Total,Amount and Surcharge are your existing columns, and are type string, you need to put CONVERT function in your column names so they will be casted to decimal(System.Decimal), if int use System.Int32 or System.Int64, etc):
dt.Columns["Total"].Expression =
"CONVERT(Amount,System.Decimal) + CONVERT(Surcharge,System.Decimal)";
[EDIT]
Just do it in your backend:
select *, CONVERT(SERTAX(Rs), DECIMAL)
+ CONVERT(STT(Rs), DECIMAL) AS brokerage
from tbl
If you have control in your database, modify the SERTAX and STT function so it can return decimal/currency/int, not string.
Then in your front-end, do this:
dt.ColumnChanging += (ds, de) =>
{
if (de.Column.ColumnName == "Rs")
{
decimal serTaxResult = (decimal)new SqlCommand("select SERTAX(" + de.ProposedValue + ")").ExecuteScalar();
decimal sttResult = (decimal)new SqlCommand("select STT(" + de.ProposedValue + ")").ExecuteScalar();
// if your SERTAX AND STT really return string, use this:
// decimal serTaxResult = decimal.Parse( (string) new SqlCommand("select SERTAX(" + de.ProposedValue + ")").ExecuteScalar() );
// decimal sttResult = decimal.Parse( (string) new SqlCommand("select STT(" + de.ProposedValue + ")").ExecuteScalar() );
de.Row["brokerage"] = serTaxResult + sttResult;
}
};
[EDIT]
If all your columns are string type, you have to enclosed each of them with their own CONVERTs.
.Expression = string.Format("CONVERT({0},System.String)",
"CONVERT(" + serviceTaxClmnInCNote + ", System.Int32)"
+ " + "
+ "CONVERT(" + STTClmnInCNote + ", System.Int32)"
);
Just change the System.Int32 to System.Decimal if the serviceTax and STT are money type.
Extract the data from te two columns and call the string concat function. Refer the following link
http://www.1keydata.com/sql/sql-concatenate.html

Categories

Resources