Creating SQL query in VB.net from a Checkboxlist - asp.net

I have a checkboxlist and I populate it dynamically from a database. For example after i populate the checkboxlist is like that:
Los Angeles
New York
London
Berlin
Amsterdam
I want to create a SQL query according to the checkboxes are checked. If i want to choose only one city (e.g. only New York) i want the result to be:
(City = 2)
Thats works properly but when i have multiple cities (e.g. New York, London and Amsterdam) i want the result to be for example:
(City = 2) OR (City = 3) OR (City = 5)
Or if i choose Los Angeles and Berlin I want the result to be like this:
(City = 1) OR (City = 4)
How can i achieve this? That's my code below but I am stacked. Any ideas?
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim var As String = ""
Dim counter As Integer = 0
Dim myList As New List(Of String)()
For i As Integer = 0 To CheckBoxList1.Items.Count - 1
If CheckBoxList1.Items(i).Selected Then
myList.Add(i + 1)
counter = counter + 1
If counter = 1 Then
var = "(City =" & i + 1 & ")"
Else
Console.WriteLine(myList(1))
Dim myArray As String() = myList.ToArray()
For j As Integer = 1 To myArray.Length
Dim var2 As String = " OR (City =" & counter & ")"
var = "(City =" & myArray(0) & ")" & var2
Next
End If
End If
Next
SQL = "SELECT * FROM Data1 WHERE (" & var & ") ORDER BY [ID]"
Session("Search") = SQL
Server.Transfer("Data_Form.aspx")
End Sub

What I recommend most strongly is to look into Table-value Parameters:
http://msdn.microsoft.com/en-us/library/bb675163(v=vs.110).aspx
This will fix your issue and help you avoid sql injection vulnerabilities.
But if you really insist on using string concatenation, try using an IN() condition, where you end up with something more like CITY IN (1,2) instead of (City = 1 OR City = 2). You can make this a bit easier to write by leading with an unused ID, like so:
Dim cityClause As String = " CITY IN (-1{0})" 'start with a valid clause
Dim cityIDs As String = ""
For Each box As ListItem In CheckBoxList1.Items.Where(Function(b) b.Selected)
'Try storing the ID for each city in the value part of each listitem,
' rather than using the index order
cityIDs = cityIDs & "," & box.Value
Next box
cityClause = string.Format(cityClause, cityIDs)

You can use City IN(2,3,5) instead of (City = 2) OR (City = 3) OR (City = 5):
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim condition As String = ""
For i As Integer = 0 To CheckBoxList1.Items.Count - 1
If CheckBoxList1.Items(i).Selected Then
condition = condition & "," & (i + 1)
End If
Next
SQL = "SELECT * FROM Data1 WHERE (" & condition.SubString(1) & ") ORDER BY [ID]"
Session("Search") = SQL
Server.Transfer("Data_Form.aspx")
End Sub

Related

Retrieving values from dynamically created controls

First post, so go easy on me.
I've been coding for years, first with VB6, then VB.NET and more recently ASP.NET. I'm ashamed to say, this issue has beaten me to the point where I need to ask for help. What's more annoying is that this should be a simple thing to achieve! I'm clearly missing something here.
I'm creating checkbox controls dynamically, quite a few of them in fact. Two per dynamically created table row and their IDs are appended with the ID of the particular DB record on the row, row 1, 2, 3 etc. So on each row there would be two checkboxes, ihave_check_1, ineed_check_1. The next row would be ihave_check_2 and ineed_check_2 and so on.
There is a submit button at the bottom of the page, and when clicked, it's supposed to loop through each row (and cell) in the table and pick out controls whose IDs contain "ihave_check_" and "ineed_check_" then get their Checked value. Once I have the values, I add a record into the database.
Problem is, when you click the button, the table disappears and so do the values.
From what I've read so far, this is happening because the controls are dynamically created, if they were static (coded in the HTML section) I wouldn't have this problem.
So first question, what do I need to do to get it working?
And second question, why is using dynamic controls so difficult?
Here's the code setting up the table, which works great:
Private Sub ddCardSeries_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ddCardSeries.SelectedIndexChanged
If IsPostBack = True And Not ddCardSeries.SelectedValue = "Select..." Then
cardsTable.Visible = True
Dim dat As New DataLayer3.DataConnector
dat.DataConnector("Provider=SQLOLEDB;Server=192.XXX.XXX.XXX;Database=GPKDB;User Id=sa;Password=XXXXXXXXXXX;")
Dim dtSections As New DataTable
dtSections = dat.DataSelect("SELECT baseCardID,baseCardSeries,baseCardNumber,baseCardName,frontArtist,conceptArtist,backArtist,backWriter,isBaseCard,isDieCut,isMatte,isGlossy,differentBack,frontImage,backImage FROM baseCards where baseCardSeries = '" & Split(Split(ddCardSeries.Text, "(ID:")(1), ")")(0) & "' and isBaseCard = 'Yes'")
If dtSections.Rows.Count > 0 Then
For i As Integer = 0 To dtSections.Rows.Count - 1
Dim row As New TableRow
For x = 0 To dtSections.Columns.Count - 1
Dim cell1 As New TableCell
If Not IsDBNull(dtSections.Rows(i)(x)) Then
If x = 0 Then
cell1.Text = dtSections.Rows(i)(x)
ElseIf x = 1 Then
cell1.Text = get_card_series(dtSections.Rows(i)(x))
ElseIf x = 13 Then
cell1.Text = "<img src='" & dtSections.Rows(i)(x) & "' height='120'"
ElseIf x = 14 Then
cell1.Text = "<img src='" & dtSections.Rows(i)(x) & "' height='120'"
Else
cell1.Text = dtSections.Rows(i)(x)
End If
Else
cell1.Text = ""
End If
row.Cells.Add(cell1)
Next x
Dim newbutton As New Button
Dim newlabel As New Label
newlabel.Text = "<br />"
newbutton.Text = "Modify this entry"
newbutton.Width = 120
newbutton.ID = "modify_button_" & dtSections.Rows(i)(0)
Dim newcheck1 As New CheckBox
Dim newlabel2 As New Label
newlabel2.Text = "<br />"
newcheck1.Text = "I own this card"
newcheck1.Width = 120
newcheck1.ID = "ihave_check_" & dtSections.Rows(i)(0)
Dim newcheck2 As New CheckBox
newcheck2.Text = "I need this card"
newcheck2.Width = 120
newcheck2.ID = "ineed_check_" & dtSections.Rows(i)(0)
Dim cell2 As New TableCell
If is_user_admin() = True Then
newbutton.Enabled = True
Else
newbutton.Enabled = False
End If
cell2.Controls.Add(newbutton)
cell2.Controls.Add(newlabel)
cell2.Controls.Add(newcheck1)
cell2.Controls.Add(newlabel2)
cell2.Controls.Add(newcheck2)
row.Cells.Add(cell2)
cardsTable.Rows.Add(row)
Next
End If
Else
cardsTable.Visible = False
End If
End Sub
Here's the code that loops through the table and tries to save the results to the database:
Protected Sub SubmitChanges_Click(sender As Object, e As EventArgs) Handles SubmitChanges.Click
For Each pcontrol As control In Page.Controls
Dim havecard As String = Nothing
Dim needcard As String = Nothing
Dim rowcardid As String = Nothing
'For Each tabcell As TableCell In tabrow.Cells
'For Each pgcontrol As Control In tabcell.Controls
If TypeOf pcontrol Is CheckBox And Split(pcontrol.ID, "_")(0) = "ihave" Then
rowcardid = Split(pcontrol.ID, "_")(2)
Dim chkbox As CheckBox = pcontrol
If chkbox.Checked = True Then
havecard = "Yes"
Else
havecard = "No"
End If
End If
If TypeOf pcontrol Is CheckBox And Split(pcontrol.ID, "_")(0) = "ineed" Then
rowcardid = Split(pcontrol.ID, "_")(2)
Dim chkbox As CheckBox = pcontrol
If chkbox.Checked = True Then
needcard = "Yes"
Else
needcard = "No"
End If
End If
'Next
If Not havecard = Nothing And Not needcard = Nothing Then
If add_card_to_user_list(Session("username"), rowcardid, havecard, needcard) = True Then
Label1.Text = "Update complete"
Else
Label1.Text = "Update failed"
End If
End If
'Next
Next
End Sub
Public Function add_card_to_user_list(ByVal userid As String, ByVal cardid As String, ByVal own As String, ByVal need As String) As Boolean
Try
Dim dat As New DataLayer3.DataConnector
dat.DataConnector("Provider=SQLOLEDB;Server=192.XXX.XXX.XXX;Database=GPKDB;User Id=sa;Password=XXXXXXXX;")
Dim dtCardSeries As New DataTable
dtCardSeries = dat.DataSelect("select CardID from [" & userid & "_cards] where cardid = '" & cardid & "'")
If dtCardSeries.Rows.Count > 0 Then
dat.DataDelete("delete from [" & userid & "_cards] where cardid = '" & cardid & "'")
End If
dat.DataInsert("insert into [" & userid & "_cards] (Username,CardID,Own,Need) values ('" & userid & "', '" & cardid & "', '" & own & "', '" & need & "');")
Return True
Catch ex As Exception
Return False
End Try
End Function
Any help at this point would be gratefully received.
Thanks!

What's the best way to parse an SQL fragment string into a List(of string) for a Listbox control?

I'm trying to take this string:
(("DISPLAY_NAME" like N'sadf%') And ("ID" = 2) And ("IsCRITERION" = null))
and parse it into a List(of string) so that it can be displayed like:
(
(
"DISPLAY_NAME" like N'sadf%'
)
And
(
"ID" = 2
)
Or
(
"IsCRITERION" = null
)
)
I'm close but don't quite have it. My code currently looks like:
Dim filterlist As New List(Of String)
Dim temp As String = String.Empty
Dim lvl As Integer = 0
Dim pad As String = String.Empty
For Each chr As Char In originalString '--- filter is the string i posted above
Select Case chr.ToString.ToLower()
Case "("
filterlist.Add(pad.PadLeft(lvl * 5) & chr)
lvl += 1
Case ")"
filterlist.Add(pad.PadLeft(lvl * 5) & temp)
If lvl > 0 Then lvl -= 1
filterlist.Add(pad.PadLeft(lvl * 5) & chr)
'If lvl > 0 Then lvl -= 1
temp = String.Empty
Case Else
temp &= chr
End Select
Next
'--- Removes the empty line produced by generating the List(of String)
filterlist = filterlist.Where(Function(s) Not String.IsNullOrWhiteSpace(s)).ToList()
listSelectedCriteria.DataSource = filterlist
listSelectedCriteria.DataBind()
Unfortunately, the above code produces something close to what I desire but the "And"s and "Or"s are not in the right places:
(
(
"DISPLAY_NAME" like N'sadf%'
)
(
And "ID" = 2
)
(
Or "IsCRITERION" = null
)
)
Would using regular expressions be better? Thanks for the help
Probably the "best" way (although that's getting into "primarily opinion-based" territory) would be to use a parser, but assuming that your input is limited to similar looking strings, here's what I came up with:
Dim originalString = "((""DISPLAY_NAME"" like N'sadf%') And (""ID"" = 2) And (""IsCRITERION"" = null))"
Dim filterlist = New List(Of String)()
Dim temp = New StringBuilder()
Dim lvl = 0
Dim addLine =
Sub(x As String)
filterlist.Add(New String(" ", lvl * 4) & x.Trim())
End Sub
For Each c In originalString
Select Case c
Case "("
If temp.Length > 0 Then
addLine(temp.ToString())
temp.Clear()
End If
addLine("(")
lvl += 1
Case ")"
If temp.Length > 0 Then
addLine(temp.ToString())
temp.Clear()
End If
lvl -= 1
addLine(")")
Case Else
temp.Append(c)
End Select
Next
If temp.Length > 0 Then
addLine(temp.ToString())
temp.Clear()
End If
filterlist.Dump() ' LINQPad ONLY
This results in:
(
(
"DISPLAY_NAME" like N'sadf%'
)
And
(
"ID" = 2
)
And
(
"IsCRITERION" = null
)
)
However, you will probably end up having to add code as you find different inputs that don't quite work how you want.
Instead of looking at each characters, I would start be doing a split. And then add/remove padding depending on what character is at the start.
Dim tempString As String = "((""DISPLAY_NAME"" like N'sadf%') And (""ID"" = 2) And (""IsCRITERION"" = null))"
Dim curPadding As String = ""
Const padding As String = " "
Dim result As New List(Of String)
For Each s As String In Text.RegularExpressions.Regex.Split(tempString, "(?=[\(\)])")
If s <> "" Then
If s.StartsWith("(") Then
result.Add(curPadding & "(")
curPadding &= padding
result.Add(curPadding & s.Substring(1).Trim())
ElseIf s.StartsWith(")") Then
curPadding = curPadding.Substring(padding.Length)
result.Add(curPadding & ")")
result.Add(curPadding & s.Substring(1).Trim())
Else
result.Add(curPadding & s)
End If
End If
Next

Index was out of range. Must be non-negative and less than the size of the collection - chart databind

I'm trying to build a datatable and then bind it to a gridview and chart object. The gridview appears fine but when I build the x,y array and bind them to the chart object I get the error above.
I've read many forums to understand that the index is looking at a field that is out of range but I've queried in the immediate window all the fields and the are clearly values there. There error occurs as soon as I bind it to the chart object and I don't know why the chart object doesn't just display properly.
This is my aspx codebehind:
Dim dt As DataTable = New DataTable()
dt.Columns.Add("CompanyName")
dt.Columns.Add("Amount")
dt.Columns.Add("Proportion")
Using DBContext As New fundmatrixEntities
Dim queryUnits = (From c In DBContext.Units Where c.SavingApplicationId = savAppId Select New With {.LoanAppId = c.LoanApplicationId}).Distinct().ToList()
Dim companyName As String = ""
Dim savingsAmount As String = ""
Dim totalProportion As String = ""
Dim totalSavingsAmount As String = ""
For Each loan In queryUnits
If Not loan.LoanAppId Is Nothing Then
companyName = classSQLDirect.ExecQuery("SELECT companyname FROM companyprofile where loanapplicationid='" & loan.LoanAppId.ToString & "'")
savingsAmount = classSQLDirect.ExecQuery("SELECT SUM(Amount) from unit where SavingApplicationId='" & savAppId.ToString & "' and LoanApplicationId='" & loan.LoanAppId.ToString & "'")
totalSavingsAmount = classSQLDirect.ExecQuery("SELECT amount FROM SavingApplication WHERE SavingApplicationId='" & savAppId.ToString & "'")
totalProportion = ((savingsAmount / totalSavingsAmount) * 100) & "%"
dt.Rows.Add(companyName, savingsAmount, totalProportion)
End If
Next
gvwBusinesses.DataSource = dt
gvwBusinesses.DataBind()
End Using
Dim x As String() = New String(dt.Rows.Count - 1) {}
Dim y As String() = New String(dt.Rows.Count - 1) {}
For i As Integer = 0 To dt.Rows.Count - 1
x(i) = dt.Rows(i)(0).ToString()
y(i) = dt.Rows(i)(2).ToString()
Next
chart1.Series(0).Points.DataBindXY(x, y)
chart1.Series(0).ChartType = SeriesChartType.Pie
The code errors on the line
chart1.Series(0).Points.DataBindXY(x, y)

Array list error second array replace the first array

I have a problem.
Dim Maxis As String
'Dim MaxisExtra As String
Dim b As New ArrayList
Dim WS As New WebService1.Service1
Dim cnt As String
Dim MRWS As New MobileReload_WS.MobileReload_WS
cnt = WS.StockCountTelco(1, Session("Maxis"))
If CInt(cnt) >= CInt(DropDownList1.SelectedItem.Text) Then
Dim sLock As String
sLock = MRWS.LockAStock(1, 1, "Online", Session("Maxis"), DropDownList1.SelectedItem.Text)
Session("sLock") = sLock
If sLock = "" Then
PopupMsgBox("Unable to allocate Stock")
Else
Maxis = "Maxis" & ";" & Session("Maxis") & ";" & DropDownList1.SelectedItem.Text & ";" & Session("Cost")
'If MaxisExtra = "" Then
' b.Add(Maxis)
' Elseif
' MaxisExtra = MaxisExtra + Maxis
' b.Add(MaxisExtra)
'End If
End If
Else
PopupMsgBox("Not enough stock")
End If
b.Add(Maxis)
Session("Transaction") = b
End Sub
The first time i enter the string into the arraylist it is okay. But when the user press the button add again the second time, it replace the first string. Can anyone help me how to save the string into the second slot based on my coding?
If you're talking about the b ArrayList, then you're creating a new one each time and storing the new ArrayList in Session("Transaction")
Maybe you mean something like this instead...
Dim b as ArrayList = Session("Transaction")
If b Is Nothing Then
b = new ArrayList
End If
...
Session("Transaction") = b
Although it's difficult to say exactly, because your code is very messy and not clear
You put the array list in a session variable, but you never read it back. You create a new array list each time, so it will always be empty and replace the previous one.
Get the array list from the session variable if there is one:
Dim b As ArrayList = Session("Transaction")
If b Is Nothing Then b = New ArrayList

ASP.Net String Split not working

Here's my code
Dim RefsUpdate As String() = Session("Refs").Split("-"C)
Dim PaymentsPassedUpdate As String() = Session("PaymentsPassed").Split("-"C)
Dim x as Integer
For x = 1 to RefsUpdate.Length - 1
Dim LogData2 As sterm.markdata = New sterm.markdata()
Dim queryUpdatePaymentFlags as String = ("UPDATE OPENQUERY (db,'SELECT * FROM table WHERE ref = ''"+ RefsUpdate(x) +"'' AND bookno = ''"+ Session("number") +"'' ') SET alpaid = '"+PaymentsPassedUpdate(x) +"', paidfl = 'Y', amountdue = '0' ")
Dim drSetUpdatePaymentFlags As DataSet = Data.Blah(queryUpdatePaymentFlags)
Next
I don't get any errors for this but it doesn't seem to working as it should
I'm passing a bookingref like this AA123456 - BB123456 - CC123456 - etc and payment like this 50000 - 10000 - 30000 -
I basically need to update the db with the ref AA123456 so the alpaid field has 50000 in it.
Can't seem to get it to work
Any ideas?
Thanks
Jamie
I'm not sure what isn't working, but I can tell you that you are not going to process the last entry in your arrays. You are going from 1 to Length - 1, which is one short of the last index. Therefore, unless your input strings end with "-", you will miss the last one.
Your indexing problem mentioned by Mark is only one item, but it will cause an issue. I'd say looking at the base your problem stems from not having trimmed the strings. Your data base probably doesn't have spaces leading or trailing your data so you'll need to do something like:
Dim refsUpdateString as string = RefsUpdate(x).Trim()
Dim paymentsPassedUpdateString as string = PaymentsPassedUpdate(x).Trim()
...
Dim queryUpdatePaymentFlags as String = ("UPDATE OPENQUERY (db,'SELECT * FROM table WHERE ref = ''" & refsUpdateString & "'' AND bookno = ''" & Session("number") & "'' ') SET alpaid = '" & paymentsPassedUpdateString & "', paidfl = 'Y', amountdue = '0' ")
Also, I would recommend keeping with the VB way of concatenation and use the & character to do it.

Resources