Building SQL IN statement from listbox control - c#

I'm trying to build a SQL query using StringBuilder and I've become stuck trying to do part of the WHERE clause.
I have a list box with a bunch of values and allows multiple selection. I need to iterate through the selected items and put then in an IN statement like...
WHERE SOME_FIELD IN ('Value','NextValue','AnotherValue')
so far I've written the code like this...
if (lstSalesGroup.SelectedItem != null)
{
selectQuery.Append("AND SALES_GROUP IN (");
foreach (ListItem item in lstSalesGroup.Items)
{
if (item.Selected)
selectQuery.Append("'" + item.Value + "',");
}
selectQuery.Append(")");
}
I need to test if the item is the last in the loop so that it doesn't put on the "," before the closing ")".
How can I do this? Or if there's a better way to build this part of the query please do suggest, I am still learning, we all have to start somewhere! :)
Eventually this will be a query for a part search.
Thanks in advance

Couple of ways for doing that.
You can use string.TrimEnd to remove the extra comma from the string or you can create a new string using string.Join like
string InPartQuery = string.Join(",", lstSalesGroup.Items
.Cast<ListItem>()
.Where(t => t.Selected)
.Select(r => "'" + r.Value + "'"));

You could use String.Join with some Linq
For clearity I've put the code in variables.
if (lstSalesGroup.SelectedItem != null)
{
var queryStr = "AND SALES_GROUP IN ({0})";
var selectedItemValues = (from itm in lstSalesGroup.Items.Cast<ListItem>()
where itm.Selected
select String.Format("'{0}'", itm));
selectQuery.Append(String.Format(queryStr, String.Join(",", selectedItemValues)));
}

Try using linq
selectQuery.Append("AND SALES_GROUP IN (");
selectQuery.Append(string.Join(",", lstSalesGroup.Items.Select(i => "'" + i.Value + "'")));
selectQuery.Append(")");
This will solve your problem, but you have a problem with SQL injection here. I would strongly advice you to use parameters in your query.

Dim s As String = "'"
For i = 0 To ListBox1.Items.Count - 1
s = s & ListBox1.Items.Item(i) & "','"
Next

Try this:
if (lstSalesGroup.SelectedItem != null)
{
selectQuery.Append("AND SALES_GROUP IN (");
var local = lstSalesGroup.Items.Where(c => c.Selected)
.Select(c => "'"+c.Value+"'")
.Aggregate((c,n) => c+ ", "+n);
selectQuery.Append(local);
selectQuery.Append(")");
}
Look at this example for more info on the .Aggragate(...) method

Related

How to turn array into quote and comma delimited string for sql?

I have a list I want to pass into SQL but they must be single quote and comma delimited.
So List = a b c
But I need a string = 'a','b','c'
How can I accomplish this in a concise manner?
Something like this I think but can't see within LINQ how to add to beginning and end:
String.Join(",", arr.Select(p => p.ToString()).ToArray())
Maybe something along the lines of:
String.Join(",", arr.Select(p=> "'" + p.ToString() + "'").ToArray());
// or is p already a string
String.Join(",", arr.Select(p => "'" + p + "'").ToArray());
You can do this:
String.Join(",", arr.Select(p => $"'{p.ToString()}'").ToArray());
And that will put the ' on either side of p.ToString() for each element.
Use an ORM that supports the following construction:
string[] items = GetItems();
var query = db.Rows.Where(row => items.Contains(row.ColumnName));
This way, you do not open yourself to sql injection by constructing strings to hand to the database yourself.
You should also be careful if your source data contains "'" in which case you need to escape the "'". Try this:
var arr = new [] { "a'c", "b" };
var output = String.Join(",", arr.Select(p => $"'{p.Replace("'", "''")}'"));
That gives "'a''c','b'".

LINQ Groupby C# from CSV

I successfully created a CSV file from a while loop. I ultimately need my code to generate another CSV file that has GroupBy information.
It looks something like this:
while (code)
{
output3 = split[5].Replace(',', ' ') + ',' +
split[0].Substring(0, 2) + "-" +
split[0].Substring(2, 4) + ',' +
split[4] + ",," + sentprice + ',' +
split[3] + ',' +
split[2] + ',' + calccharge + ',' +
split[1] + ",,," + "NA" + ',' + "A" + ',' +
split[0].Substring(6, 5) + Environment.NewLine + output3;
}
Now I'm trying to split output3 so that I can group by one of the columns (i.e. split[1]).
I've tried:
var table = File.ReadAllLines(FilePath)
.Select(record => record.Split(','))
.Select(cell => new { AFPCode = cell[1] })
.GroupBy(x => x.AFPCode);
but that result gives me an index was outside the bounds of the array. As you can see the index is inside the bounds of the array.
I've also tried:
IEnumerable<string> table =
from row in File.ReadAllLines(FilePath)
let elements = row.Split(',')
let cell = new {AFPCode = elements[1]}
group p by p.AFPcode into g
That is also not working. Any help will be much appreciated.
Some rows are missing the 2nd column. Did you try filtering out those rows like below?
var table = File.ReadAllLines(FilePath)
.Select(record => record.Split(','))
.Where(cell => cell.Length >= 2) // Add filter clause here
.Select(cell => new { AFPCode = cell[1] })
.GroupBy(x => x.AFPCode);
You have an empty line at the end of your file. That empty line doesn't have a second item when you split it into fields. Either remove the empty line at the end, or filter out the empty line in the code you're using to read in the file.
Some side notes, you shouldn't be constructing large files by using the + operator to concat the strings to each other in a loop. It's a particularly inefficient operation. You can use string.Join to efficiently join a bunch of strings together (either all fields on a line or all lines in a file).
The other option is to write out each line to the file as you compute it (this is actually better still, as you then never have more than one line in memory). This can be done rather easily using File.WriteAllLines if you have a sequence of all of your lines.

Concatenating two fields in LINQ select

I have a dropdownlist, ddCourse, that I'm populating with the following LINQ query:
var db = new DataClasses1DataContext();
ddCourse.DisplayMember = "COURSE_TITLE";
ddCourse.ValueMember = "COURSE_ID";
ddCourse.DataSource = db.COURSE_MASTERs.OrderBy(c => c.COURSE_TITLE)
.Select(c => new { c.COURSE_ID, c.COURSE_TITLE })
.ToList();
There's another field, though, that I'd like to concatenate to the COURSE_TITLE field in my selection. So, I'd like my selection to look like:
.Select( c => new {c.COURSE_ID, c.CIN + " " + c.COURSE_TITLE})
The only problem is that this, apparently, isn't how it's done. I'm basically wanting to join c.CIN with c.COURSE_TITLE (and have a space in the middle). Can someone offer me some pointers on how to accomplish this?
The reason I want to do this is that, right now, the only thing appearing in the dropdownlist is the course title. I'd like to have the course ID number (CIN) concatenated to it when it displays.
EDIT: For clarification, I'm using Linq-to-SQL.
use this
.Select( c => new {c.COURSE_ID, COURSE_TITLE =string.Format("{0} {1}" ,c.CIN ,c.COURSE_TITLE)})
You need to name your anonymous members:
.Select( c => new {COURSE_ID = c.COURSE_ID, COURSE_TITLE = c.CIN + " " + c.COURSE_TITLE})
Write your Select like this:
.Select( c => new {c.COURSE_ID, COURSE_TITLE = c.CIN + " " + c.COURSE_TITLE})
Anonymous types need to have their column names specified, in case they cannot be inferred.
For c.COURSE_ID C# is smart enough to generate a member called COURSE_ID in the anonymous type. For the expression c.CIN + " " + c.COURSE_TITLE it cannot.

How to use Linq aggregate with single quotes

Let's assume that I have a collection of strings, like so:
IList<string> myList = new List<string>(){"one", "two", "three"};
Using myList.Aggregate I would like to end up with "'one', 'two', 'three'" (including single quotes)
Does someone have a sleak way of doing this, only using the Aggregate function? I was thinking something in the lines of
myList.Aggregate((increment, seed) => string.Concat(increment, ", ", seed));
but that's only half the solution.
Any reason to use Aggregate rather than the simpler string.Join?
string joined = string.Join(", ", myCollection.Select(x => "'" + x + "'"));
(Add a ToArray call if you're using .NET 3.5.)
You can implement string.Join using Aggregate (ideally using a StringBuilder) but it's not terribly pleasant. Assuming a non-empty collection, I think this should do it:
string csv = myCollection.Aggregate(new StringBuilder("'"),
(sb, x) => sb.AppendFormat("{0}', '"),
sb => { sb.Length -= 3;
return sb.ToString(); });
Since you specify "only using the Aggregate function", how about:
myCollection.Aggregate(string.Empty, (soFar, next) =>
soFar + (soFar == string.Empty ? soFar : ", ")
+ "'" + next + "'")
(or)
myCollection.Aggregate(string.Empty, (soFar, next) =>
string.Format("{0}{1}'{2}'",
soFar, soFar == string.Empty ? soFar : ", ", next))
Using Aggregate in this manner for string concatenation is really inefficient though.
EDIT: Updated to get rid of the leading ,.

C# Converting ListBox to String then Aggregate

I have a listbox being populated from a combo box. What i need to do is string all the contents of the listbox together and then Aggregate it.
string cols = listbox1.items.Aggregate((f, s) => f.value + "," + s.value);
doesnt work.
Items is an ObjectCollection, so all you know for sure is that it contains objects. You can call ToString on any object:
string[] items = listBox1.Items
.OfType<object>()
.Select(item => item.ToString())
.ToArray();
string result = string.Join(",", items);
Note that this is both more readable and more efficient than using aggregate, which causes multiple string concatenations.
pretty old thread, but here's my solution if anybody need it still
string cols = string.Join(",", listBox1.Items.Cast<String>());
Supposing that you have strings in the listbox, try this:
string cols =
String.Join(",", listbox1.Items
.OfType<Object>()
.Select(i => i.ToString())
.ToArray());
Generally String.Join is used to join a string. This is faster than using a StringBuilder as the size of the new string is already known and it doesn't have to copy everything twice.
string cols = listBox1.Items.Cast<string>().Aggregate((f, s) => f + "," + s);
I think you need to explicitly do ToString()
string cols = listbox1.items.Aggregate((f, s) => f.value.ToString() + "," + s.value.ToString());

Categories