0

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

5 Answers 5

4

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 + "'"));
Sign up to request clarification or add additional context in comments.

3 Comments

+1 for laconic LINQ, but you should add filter by selected items
This is perfect! Thank you very much @Habib :) What is laconic LINQ? how is it different from regular LINQ?
@Stuart, nothing it is regular LINQ, its just the writing style :) see define: laconic
1

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)));
}

2 Comments

You are missing quotes around values. And I don't sure if itm will not be of object type
@lazyberezovsky Thanks, I missed that so I've edited it. Should be alright now.
1

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.

3 Comments

Thanks for pointing this out. I thought it was safe from injection if I'm programatically populating the select options?
This is a common mistake but there is a potential risk for SQL injection here. Imagine that someone somehow managed to get the value "') Drop table SomeTable;--" into your list. Can you see what your final query would look like? =)
...something like my P45!! I'll put all the final values into parameters. thanks!
0
Dim s As String = "'"
    For i = 0 To ListBox1.Items.Count - 1
        s = s & ListBox1.Items.Item(i) & "','"
    Next

2 Comments

This doesn't really look like C# ;-) And please provide some explanation, to improve your answer.
Question is about C#, this is Visual Basic.
0

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

4 Comments

That will produce correct result, but I think that aggregating strings without StringBuilder will produce many unnecessary strings. Simple String.Join will be better here
@lazyberezovsky I agree. string.Join is simpler. I just didn't thought of it :) My mind is "linq'ed"
Here is a hint how to stay with LINQ, but avoid messing memory with strings Aggregate(new StringBuilder(), (sb,s) => sb.Append(s), sb => sb.ToString()) :)
@lazyberezovsky Darn interesting approach, never investigated that overload in Aggregate. +1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.