views:

1901

answers:

2

I'm trying to build a list that will be used as the in clause of a select statement. The requirement is to have the user enter a comma separated list of descriptions. Each description can contain spaces so I can't remove the spaces before splitting by comma to add the single quotes around each description. I want to remove all white space after a single quote since no description will start with a space. What's the best way to do this in VB.NET? Regular expression or a string function? Here's what I have so far.:

Partial Class Test
    Inherits System.Web.UI.Page

    Protected Sub cmdGetParts_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdGetParts.Click
        Dim sDescriptionList As String = ""
        BuildList(sDescriptionList)
        RemoveSpacesFromList(sDescriptionList)
        FillGrid(sDescriptionList)
    End Sub

    'Build descriptions List based on txtDescriptionList.Text
    Private Sub BuildList(ByRef sDescriptionList As String)
        Dim sDescriptionArray As String()
        sDescriptionArray = txtDescriptionList.Text.Trim.Split(","c)
        Dim iStringCount As Integer = 0
        For Each description In sDescriptionArray
            If iStringCount > 0 Then
                sDescriptionList = sDescriptionList & ","
            End If
            sDescriptionList = sDescriptionList & "'" & description & "'"
            iStringCount = iStringCount + 1
        Next
    End Sub

    **'This procedure removes unwanted spaces from  description list
    Private Sub RemoveSpacesFromList(ByRef sList As String)
        sList = sList.Replace("' ", "'")
    End Sub**

    'This procedure fills the grid with data for descriptions passed in
    Private Sub FillGrid(ByVal sDescriptionList As String)
        Dim bo As New boPart
        Dim dtParts As Data.DataTable
        dtParts = bo.GetPartByDescriptionList(sDescriptionList)
        GridView1.DataSource = dtParts
        GridView1.DataBind()
    End Sub
End Class

Edited: After reviewing this code I think I may be able to just place description.Trim inside the For Each loop of the BuildList procedure.

+2  A: 

As long as you cannot have embedded single quotes, the following should do the trick

Dim replaced = Regex.Replace(input, "'\s+", "'")

The regex string '\s+ will match any single quote followed by one or more white space characters. All instances of this match will be replaced by a single quote.

JaredPar
+1  A: 

Use a regular expression to match a comma with any surrounding white space, and replace with apostropes and a comma. The starting apostrope for the first item and the ending apostrophe for the last item you simply add afterwards.

The RemoveSpacesFromList method is no longer needed, as the BuildList method does it all.

Protected Sub cmdGetParts_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdGetParts.Click
    Dim descriptions As String = txtDescriptionList.Text
    descriptions = BuildList(descriptions)
    FillGrid(descriptions)
End Sub

''//Build descriptions List based on a comma separated string
Private Function BuildList(ByVal descriptions As String) As String
   Return "'" + Regex.Replace(descriptions, "\s*,\s*", "','", RegexOptions.Compiled) + "'"
End Function

Note:
If you are using this string to build an SQL query, your application is wide open for SQL injection attacks. Using parameterised queries is the preferred method, but that might not be convenient in your case. User input has to at least be sanitised before being used in a query.

Edit:
If the adapter uses apostrophes as escape character in a string literal, you can escape the string properly like this:

Private Function BuildList(ByVal descriptions As String) As String
   Return "'" + Regex.Replace(descriptions.Replace("'","''"), "\s*,\s*", "','", RegexOptions.Compiled) + "'"
End Function
Guffa
This really reduces the amount of code I need to write. I'm not very familiar with regular expressions. Are there any online resources that you recommend. I think there's a chapter in the .NET Applications Development foundations book I have. I need to re-read that section. What is recommended as far as performance and code readability/maintenance; regular expressions or string functions?
I using the .xsd table adapter in a DAL layer. The business object will call the table adapter extension method that I created and replace REPLACE_THIS with the description list:select * from table where description in (REPLACE_THIS)Would this still be open for SQL injection attacks since I'm only replacing what's in the IN clause?
Regular expressions tend to become complicated and thus hard to maintain, but with a simple expression like this it's not a problem. Compared to your original code this has better performance, but the original code can be rewritten using a StringBuilder to perform just as good.
Guffa
It doesn't matter what string methods you use to put together the query, a replace doesn't protect the query.
Guffa