Issues on loop for retrieve the dynamic sql parameter values from dynamic textboxes - vb.net

all. I am a new VB.NET beginner. I am facing the issue of how to pass the dynamic SQL parameter values from the dynamic textboxes to search the data. I had added control of dynamic textboxes and labels and would like to search the data on the database table based on the dynamic textboxes value inputted from the user. Currently, I can only able to search the data from 1 dynamic textbox value only.
I want all the values from the dynamic textboxes that the user had been entered can be retrieved, and search the data based on the SQL parameter variable name and value entered by the user.
Can someone give me some solutions on how to solve this problem? I had stuck on this problem for a few days. Thank you for all the help!
What I had tried:
Private Sub FilterData()
Dim count As Integer = 0
'filterdata for radiobutton
Try
For Each TextBox As TextBox In grp2.Controls.OfType(Of TextBox)()
For Each Label As Label In grp2.Controls.OfType(Of Label)()
Using connection As New SqlConnection("connectionString")
'user key in the SQL statement
sql = TextBox1.Text
Dim sql2 As String
sql2 = sql
Dim sp1 As String() = sql.Split(New String() {"where"}, StringSplitOptions.None)
sql = sp1(0) & " where " & Label.Text & " = #parameter or " & Label.Text & " =#parameter"
If (TextBox.Text <> "") Then
count += 1
For j As Integer = 0 To count - 1
Using cmd As New SqlCommand(sql, connection)
cmd.Parameters.AddWithValue("#parameter", TextBox.Text)
'cmd.Parameters.Add("#parameter", SqlDbType.NVarChar, 20).Value = TextBox.Text
connection.Open()
Dim dt As New DataTable()
Dim reader As SqlDataReader
reader = cmd.ExecuteReader()
dt.Load(reader)
DataGridView1.DataSource = dt
End Using
Next
Else
GetData()
End If
'cmd.Dispose()
connection.Close()
End Using
Next
Next
Catch ex As Exception
'MsgBox(ex.Message)
End Try
End Sub

Firstly, if you have a 1:1 correspondence between Labels and TextBoxes then you should not be using two nested For Each loops, because that is going to pair up each and every Label with each and every TextBox. What you should be doing is creating arrays and then using a single For loop to access the pairs of controls:
Dim labels = grp2.Controls.OfType(Of Label)().ToArray()
Dim textBoxes = grp2.Controls.OfType(Of TextBox)().ToArray()
For i = 0 To labels.getUpperBound(0)
Dim label = labels(i)
Dim textBox = textBoxes(i)
'...
Next
As for build the SQL and adding the parameters, I would tend to do it something like this:
Dim labels = grp2.Controls.OfType(Of Label)().ToArray()
Dim textBoxes = grp2.Controls.OfType(Of TextBox)().ToArray()
Dim criteria As New List(Of String)
Dim command As New SqlCommand
For i = 0 To labels.getUpperBound(0)
Dim label = labels(i)
Dim textBox = textBoxes(i)
Dim parameterName = "#" & label.Text.Replace(" ", "_")
criteria.Add($"[{label.Text}] = {parameterName}")
command.Parameters.AddWithValue(parameterName, textBox.Text)
Next
Dim sql = "SELECT * FROM MyTable"
If criteria.Any() Then
sql &= " WHERE " & String.Join(" OR ", criteria)
End If
command.CommandText = sql

I think that you should begin to separate UI and data logic here is an example of implementation:
First you have a table in database:
CREATE TABLE Customer (
Id INT IDENTITY (1, 1) PRIMARY KEY,
FirstName VARCHAR (255) NOT NULL,
LastName VARCHAR (255) NOT NULL,
Phone VARCHAR (25),
Email VARCHAR (255) NOT NULL,
Street VARCHAR (255),
City VARCHAR (50),
State VARCHAR (25),
ZipCode VARCHAR (5)
);
Then you create the underlying entity in VB. Net:
Public Class Customer
Public Property Id As Integer
Public Property FirstName As String
Public Property LastName As String
Public Property Phone As String
Public Property Email As String
Public Property Street As String
Public Property City As String
Public Property State As String
Public Property ZipCode As String
End Class
Data loader
Now you need a data access component that loads records to a list of this above entity here a nice implementation:
Imports System.Data.SqlClient
Public Class CustomerDataAccess
Public Property ConStr As String
Public Sub New(ByVal constr As String)
constr = constr
End Sub
Public Function GetCustomersByCriterias(constraints As Object) As List(Of Customer)
Dim query As String = "SELECT Id, FirstName, LastName, Phone, Email, Street, City, State, ZipCode
FROM [dbo].[Customer] "
Dim result = New List(Of Customer)()
Using con = New SqlConnection(ConStr)
Using cmd = con.CreateCommand()
cmd.CommandType = CommandType.Text
cmd.CommandText = query
'' here the magic to add dynamic criteria coming from constraints
cmd.ApplyConstraints(Of Customer)(constraints)
con.Open()
LoadCustomerData(cmd, result)
End Using
End Using
Return result
End Function
Private Sub LoadCustomerData(ByVal cmd As SqlCommand, ByVal result As List(Of Customer))
Using rdr = cmd.ExecuteReader()
Dim idIdx As Integer = rdr.GetOrdinal("Id")
Dim firstNameIdx As Integer = rdr.GetOrdinal("FirstName")
Dim lastNameIdx As Integer = rdr.GetOrdinal("LastName")
Dim phoneIdx As Integer = rdr.GetOrdinal("Phone")
Dim emailIdx As Integer = rdr.GetOrdinal("Email")
Dim streetIdx As Integer = rdr.GetOrdinal("Street")
Dim cityIdx As Integer = rdr.GetOrdinal("City")
Dim stateIdx As Integer = rdr.GetOrdinal("State")
Dim zipCodeIdx As Integer = rdr.GetOrdinal("ZipCode")
While rdr.Read()
Dim item = New Customer()
item.Id = rdr.GetValueOrDefault(Of Integer)(idIdx)
item.FirstName = rdr.GetValueOrDefault(Of String)(firstNameIdx)
item.LastName = rdr.GetValueOrDefault(Of String)(lastNameIdx)
item.Phone = rdr.GetValueOrDefault(Of String)(phoneIdx)
item.Email = rdr.GetValueOrDefault(Of String)(emailIdx)
item.Street = rdr.GetValueOrDefault(Of String)(streetIdx)
item.City = rdr.GetValueOrDefault(Of String)(cityIdx)
item.State = rdr.GetValueOrDefault(Of String)(stateIdx)
item.ZipCode = rdr.GetValueOrDefault(Of String)(zipCodeIdx)
result.Add(item)
End While
End Using
End Sub
End Class
Extensions methods
Below are extensions methods referenced above that do the magic you are looking for:
DataReader extensions to make it easy to read values from SalDataReader with Dbnull exfeptional case and casting
Module DataReaderExtenions
<Extension()>
Function GetValueOrDefault(Of T)(row As IDataRecord, fieldName As String) As T
Dim ordinal = row.GetOrdinal(fieldName)
Return row.GetValueOrDefault(Of T)(ordinal)
End Function
<Extension()>
Function GetValueOrDefault(Of T)(row As IDataRecord, ordinal As Integer) As T
Return (If(row.IsDBNull(ordinal), Nothing, row.GetValue(ordinal)))
End Function
<Extension()>
Function GetValueOrDefaultSqlite(Of T)(row As IDataRecord, fieldName As String) As T
Dim ordinal = row.GetOrdinal(fieldName)
Return row.GetValueOrDefault(Of T)(ordinal)
End Function
<Extension()>
Function GetValueOrDefaultSqlite(Of T)(row As IDataRecord, ordinal As Integer) As T
Return (If(row.IsDBNull(ordinal), Nothing, Convert.ChangeType(row.GetValue(ordinal), GetType(T))))
End Function
End Module
Command extensions that lets you extract criteria from an anonymous object values:
Imports System.Reflection
Imports System.Runtime.CompilerServices
Module CommandExtensions
<Extension()>
Function AddParameter(command As IDbCommand, name As String, value As Object) As IDataParameter
If command Is Nothing Then Throw New ArgumentNullException("command")
If name Is Nothing Then Throw New ArgumentNullException("name")
Dim p = command.CreateParameter()
p.ParameterName = name
p.Value = If(value, DBNull.Value)
command.Parameters.Add(p)
Return p
End Function
<Extension()>
Function ToDictionary(data As Object) As Dictionary(Of String, Object)
If TypeOf data Is String OrElse data.[GetType]().IsPrimitive Then Return New Dictionary(Of String, Object)()
Return (From [property] In data.[GetType]().GetProperties(BindingFlags.[Public] Or BindingFlags.Instance)
Where [property].CanRead
Select [property]).ToDictionary(Function([property]) [property].Name, Function([property]) [property].GetValue(data, Nothing))
End Function
<Extension()>
Sub ApplyConstraints(Of TEntity)(cmd As IDbCommand, constraints As Object)
If constraints Is Nothing Then Return
Dim dictionary = constraints.ToDictionary()
Dim whereClause = " WHERE "
For Each kvp In dictionary
Dim columnName = kvp.Key
Dim propertyName = kvp.Key
Dim prefix = "#"c
Dim value = kvp.Value
whereClause += $"{columnName} **like** {prefix}{propertyName} AND "
cmd.AddParameter(propertyName, value)
Next
If String.IsNullOrEmpty(whereClause) Then Return
cmd.CommandText += whereClause.Remove(whereClause.Length - 5, 5)
End Sub
End Module
Example:
After coded all these stuff now you can do the following:
Dim DataGridView1 As DataGridView = New DataGridView()
Dim ConStr As String = ConfigurationManager.ConnectionStrings("MyApp").ConnectionString
Dim dal As CustomerDataAccess = New CustomerDataAccess(ConStr)
Dim criterias = New With {.FirstName = "%James%", .LastName = "%Nadin%"}
DataGridView1.DataSource = dal.GetCustomersByCriterias(criterias)
Despite all this code you are still need to bind your textbox (after naming them correctly) to a SearchEntity and use this entity to provide criterias
I hope this material can help you tackle your issue and incite you to improve your architecture & dev skills

Related

Defining Variables that are accessible page wide

Good morning guys,
I am working on vb.net. The aim is to make a CodeFile run some sql queries and then return the values to the webpage as an sqldatasource query parameter on page load.
I have the following vb code
Partial Class Consult
Inherits Page
Public totalCount As Integer = "0"
'*******Here i declare the variable***************
Public Property PatNo() As String
Get
Return ViewState("PatNo")
End Get
Set(ByVal value As String)
ViewState("PatNo") = value
End Set
End Property
Public PatNam As String = "abc"
Public ConID As String = "abc"
Public TreatType As String = "abc"
Public HPC As Char = "abc"
Public LvTyp As RadioButtonList
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Me.PatNo = Request.QueryString("pNo")
Session("PatientNo") = PatNo
Dim ConsultationID As String = Request.QueryString("consultID")
ConID = ConsultationID
Response.Write(PatNo)
Dim constr As String = ConfigurationManager.ConnectionStrings("DefaultConnection").ConnectionString
Using con As New SqlConnection(constr)
'**********BELOW LINE CAUSES ERROR**************
Dim query As String = "SELECT * FROM hPatients WHERE pNO=#PatNo"
query += "SELECT * FROM hPatients WHERE pNO='001/000034824'"
Using cmd As New SqlCommand(query)
cmd.Parameters.Add("#PatNo", SqlDbType.NVarChar).Value = PatNo
Using sda As New SqlDataAdapter()
cmd.Connection = con
sda.SelectCommand = cmd
Using ds As New DataSet()
sda.Fill(ds)
gvPatientInfo.DataSource = ds.Tables(0)
'Return ds.Tables(0).Rows(0).Item(2)
'Response.Write(ds.Tables(0).Rows(0).Item(2))
gvPatientInfo.DataBind()
gvClientInfo.DataSource = ds.Tables(1)
gvClientInfo.DataBind()
End Using
End Using
End Using
End Using
If Not Me.IsPostBack Then
'Dim di As DataInfo = Me.GetInfo()
'Populating a DataTable from database.
Dim dt As DataTable = Me.GetData()
'Response.Write(ConID + " " + PatNo)
'Building an HTML string.
Dim html As New StringBuilder()
'Table start.
html.Append("<table border = '1' class = 'table'>")
'Building the Header row.
html.Append("<tr>")
For Each column As DataColumn In dt.Columns
html.Append("<th>")
html.Append(column.ColumnName)
html.Append("</th>")
Next
html.Append("</tr>")
'Building the Data rows.
For Each row As DataRow In dt.Rows
html.Append("<tr>")
For Each column As DataColumn In dt.Columns
html.Append("<td>")
html.Append(row(column.ColumnName))
html.Append("</td>")
Next
html.Append("</tr>")
Next
'Table end.
html.Append("</table>")
'Append the HTML string to Placeholder.
PlaceHolder1.Controls.Add(New Literal() With { _
.Text = html.ToString() _
})
End If
End Sub
The error i get is
Must declare the scalar variable "#PatNo".
The error occurs in the first step of getting the variable to execute the query in the page_load function.
The second step would be to get the result of the query and use on the webpage.
Somebody, Anybody, Please HELP!!!.
I think the problem is with this line:
cmd.Parameters.Add("PatNo", SqlDbType.NVarChar).Value = PatNo
Change the name from "PatNo" to "#PatNo" and it should work.

Find String with row, column number from Datatable in VB.Net

Im reading excel sheet having two section as input and output section and import that to two Datagridview one for input and another one for Output section in VB.net 2008 Windows application.
If i have 10 rows and 10 columns for input section, then in my 11th row i have a text like 'End of Input Data' like the same i have in 11th column.
So by checking this,if i get the row and column number of this string i can import the data in to two data grid views. i can import only these row and column data in input gridview.
Below is the code for reading excel sheet. I don't know how to find string in Datatable. Or is there any other way to do that?
Private Sub ImpGrid_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ImpGrid.Click
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim conStr As String, sheetName As String
Dim filePath As String = "C:\SIG.XLS"
Dim extension As String = ".xls"
conStr = String.Empty
conStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & filePath & ";Extended Properties=""Excel 8.0;HDR=No;IMEX=1"""
Using con As New OleDbConnection(conStr)
Using cmd As New OleDbCommand()
Using oda As New OleDbDataAdapter()
Dim dt As New DataTable()
' cmd.CommandText = (Convert.ToString("SELECT * From [") & sheetName) + "]"
cmd.CommandText = "select * from [Sheet1$]"
cmd.Connection = con
con.Open()
oda.SelectCommand = cmd
oda.Fill(dt)
con.Close()
'Populate DataGridView.
Loggridview.DataSource = dt
End Using
End Using
End Using
End Sub
Here's a function that will returns a list of hits. Each result is a Tuple with Item1 being the rowId and Item2 being the columnId
Public Structure SearchHit
Public ReadOnly RowIndex As Integer
Public ReadOnly CellIndex As Integer
Public Sub New(rowIndex As Integer, cellIndex As Integer)
Me.RowIndex = rowIndex
Me.CellIndex = cellIndex
End Sub
End Structure
Public Function FindData(ByVal value As String, table As DataTable) As List(Of SearchHit)
Dim results As New List(Of SearchHit)
For rowId = 0 To table.Rows.Count - 1
Dim row = table.Rows(rowId)
For colId = 0 To table.Columns.Count - 1
Dim cellValue = row(colId)
If value.Equals(cellValue) Then
results.Add(New SearchHit(rowId, colId))
End If
Next
Next
Return results
End Function

When combo box data selected, fill out textbox with data from Database

I am working on an application and I have a question, I have a Combo box that is bound to a table in my databse, when data is selected in the combo box I would like 'textbox 1' and 'textbox2' to be automatically filled out with data from the table, is this possible? so say for instance when I select 'Richard' on the combo box, 'Richards' 'Address1' and 'Postcode' are filled out in text boxes. I have a sample code that does this but it only seems to work with Int32, see insterted below.
Public Class Form1
Private Sub cmdGetByIdentifier_Click(sender As Object, e As EventArgs) Handles cmdGetByIdentifier.Click
If Not String.IsNullOrWhiteSpace(txtIdentifier1.Text) Then
Dim Identifier As Int32 = 0
If Int32.TryParse(txtIdentifier1.Text, Identifier) Then
txtCompanyName1.Text = GetCustomerNameByIdentifier(Identifier)
Else
MessageBox.Show("'" & txtIdentifier1.Text & "' is not a valid integer.")
End If
Else
MessageBox.Show("Must enter an identifier to get a company name.")
End If
End Sub
Private Sub cmdGetCustomer_Click(sender As Object, e As EventArgs) Handles cmdGetCustomer.Click
If Not String.IsNullOrWhiteSpace(txtIdentifier2.Text) Then
Dim Identifier As Int32 = 0
If Int32.TryParse(txtIdentifier2.Text, Identifier) Then
Dim Cust As Customer = GetCustomer(Identifier)
txtCompanyName2.Text = Cust.Name
txtContactName2.Text = Cust.ContactName
Else
MessageBox.Show("'" & txtIdentifier1.Text & "' is not a valid integer.")
End If
Else
MessageBox.Show("Must enter an identifier to get a company name.")
End If
End Sub
End Class
Module DatabaseOperations
Public Function GetCustomerNameByIdentifier(ByVal Identifier As Int32) As String
Dim CompanyName As String = ""
Dim Builder As New OleDb.OleDbConnectionStringBuilder With {.Provider = "Microsoft.ACE.OLEDB.12.0", .DataSource = IO.Path.Combine(Application.StartupPath, "Database1.accdb")}
Using cn As New OleDb.OleDbConnection With {.ConnectionString = Builder.ConnectionString}
Using cmd As New OleDb.OleDbCommand With {.Connection = cn}
cmd.CommandText = "SELECT CompanyName FROM Customer WHERE Identifier =#P1"
Dim NameParameter As New OleDb.OleDbParameter With {.DbType = DbType.Int32, .ParameterName = "P1", .Value = Identifier}
cmd.Parameters.Add(NameParameter)
cn.Open()
CompanyName = CStr(cmd.ExecuteScalar)
End Using
End Using
Return CompanyName
End Function
Public Function GetCustomer(ByVal Identifier As Int32) As Customer
Dim Customer As New Customer
Dim CompanyName As String = ""
Dim Builder As New OleDb.OleDbConnectionStringBuilder With {.Provider = "Microsoft.ACE.OLEDB.12.0", .DataSource = IO.Path.Combine(Application.StartupPath, "Database1.accdb")}
Using cn As New OleDb.OleDbConnection With {.ConnectionString = Builder.ConnectionString}
Using cmd As New OleDb.OleDbCommand With {.Connection = cn}
cmd.CommandText = "SELECT Identifier, CompanyName,ContactName FROM Customer WHERE Identifier =#P1"
Dim NameParameter As New OleDb.OleDbParameter With {.DbType = DbType.Int32, .ParameterName = "P1", .Value = Identifier}
cmd.Parameters.Add(NameParameter)
cn.Open()
Dim Reader As OleDb.OleDbDataReader = cmd.ExecuteReader
If Reader.HasRows Then
Reader.Read()
Customer.Identifier = Identifier
Customer.Name = Reader.GetString(1)
Customer.ContactName = Reader.GetString(2)
End If
End Using
End Using
Return Customer
End Function
End Module
Public Class Customer
Public Property Identifier As Int32
Public Property Name As String
Public Property ContactName As String
Public Sub New()
End Sub
End Class
1.Refer Below Link To Fetch Data from Sql server
2.Create a Function Which Will Return your Data with ID as parameter
Dataadapter with dataset - sql sever
Not 100% sure about using Access but in theory what you would do is have a customer object
You would have a SQL Stored Procedure
Select * from Customers where id=#ID
...
Then a class
Public Class Customer
public property ID as Integer
Public property Name as string
public Property Surname as string
....
End Class
In your code where you access the data you would have something like
Public Function GetCustomerDetailsByID (byval CustomerID as Integer) As Customer ' Or whatever you want to return it as
Dim myCust as New Customer
' Code to access SQL
' Call your SQL procedure called GetCustByID(CustID)
With myCust
.Name = valueFromYourProcedure
End With
End Function
In your client app, you would then call the above, then assign the values to your controls i.e.
Dim SingleCustomer as Customer = GetCustomerDetailsByID(1) ' i.e. value form your dropdown
txtBoxName.Text = SingleCustomer.Name
Thats a very rough example and isnt fully complete but should give you some idea of how to go about this. Theres a lot of ways to do the above and everyone has their own way so you may need to do some extra research to be comfortable with it.
Hope this helps

asp.net vb website loop through database rows

I am working on my first website and need help with a loop. I have a database table containing food items named Menu with 8 categories (such as Burgers, Appetizers). I also have a menu page on website with 8 different pics to display items from each category. I need to loop through rows of database. What is happening is it's only looping through columns and repeating first line over and over. I'm aware I need a loop but for some reason cannot get that right.
This is code behind:
Partial Class Burger
Inherits System.Web.UI.Page
'String Used to build the necessary markup and product information
Dim str As String = ""
'Var used to interact with SQL database
Dim db As New Interaction
'Adds the necessary markup for each menu item, using its productName
Protected Sub printMenuBlock(ByVal productName As String)
'Set up variable storing the product
Dim product As Product
'Pull the product in from our database using the productName
product = db.ReadProduct(productName)
'Add necessary markup to str variable, with products information within
str += "<div class='storeItem'>"
' str += " <img alt='Item Picture' class='itemPicture' src='" + product.ImagePath.Substring(3).Replace("\", "/") + "' />"
' str += " <div class='itemInfo'>"
str += " <h1 class='itemName'>"
str += " " + product.Name + "</h1>"
str += " <h3 class='itemDescription'>"
str += " " + product.Description + "</h3>"
str += " <p class='itemPrice'>"
str += " " + product.Price.ToString("c") + "</p>"
str += " "
str += " </div>"
str += " </div>"
End Sub
'Uses
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim productNames As New List(Of String)
'Pull the product names using the database
productNames = db.getProductNames
'Loop through all product names
For Each name As String In productNames
'Add necessary markup and product info to str variable
printMenuBlock(name)
Next
'Print the str variable in our menuPlace div
menuPlace.InnerHtml = str
End Sub
End Class
This is functions from interaction class:
Private Sub GetProduct(ByVal CatIn As String)
' SQL String
Dim strSelect As String
strSelect = "SELECT * "
strSelect &= " FROM Menu "
' strSelect &= " WHERE (ProductCat = 'Burgers')"
' Set up the connection to the datebase
cmdSelect.Connection = conIn.Connect
' Add the SQL string to the connection
cmdSelect.CommandText = strSelect
' Add the parameters to the connection
cmdSelect.Parameters.Add("#CatIn", SqlDbType.NVarChar).Value = CatIn
End Sub
'Executes the SQL statement to find a Product by ProductId
Public Function ReadProduct(ByVal CatIn As String) As Product
' Product object initalized to nothing
Dim prod As Product = Nothing
Try
Call GetProduct(CatIn)
Dim dbr As SqlDataReader
Dim strCat As String
Dim strName As String
Dim strDesc As String
Dim decPrice As Decimal
Dim strPath As String
' Execute the created SQL command from GetProduct and set to the SqlDataReader object
dbr = cmdSelect.ExecuteReader
dbr.Read()
' Check if there are any returned values
If dbr.HasRows Then
' Assign the value in column two to strName
strCat = dbr.GetString(1)
' Assign the value in column two to strName
strName = dbr.GetString(2)
' Assign the value in column three to strDesc
strDesc = dbr.GetString(3)
' Assing the value in column four to intPrice
decPrice = ToDecimal(dbr.GetValue(4))
'Assign the value in column five to strPath
'strPath = dbr.GetString(3)
' Create the new Product object from the returned values
prod = New Product(strName, strDesc, decPrice, strCat, strPath)
End If
' Clear the SQL parameters and close the connection
cmdSelect.Parameters.Clear()
dbr.Close()
Catch ex As SqlException
Dim strOut As String
strOut = ex.Message
Console.WriteLine(strOut)
End Try
' Return the Product object
Return prod
End Function
'Returns a list of Product Names
Public Function getProductNames() As List(Of String)
Dim list As New List(Of String)
Dim sql As String = "SELECT ProductName FROM Menu " +
"WHERE (ProductCat) = 'Burgers'"
'"DISTINCT 'ProductName'"
cmdSelect.CommandText = sql
cmdSelect.Connection = conIn.Connect
Dim dbr As SqlDataReader
dbr = cmdSelect.ExecuteReader
If dbr.HasRows Then
Do While dbr.Read()
list.Add(dbr.GetString(0))
Loop
End If
dbr.Close()
Return list
End Function
There is obviously a Product Class but don't think that is necessary to show on here.
Also, ignore the string path, that will be for images later. Thanks for any help. I'm pretty sure instead of do while I need a for each somewhere but just can't get her done. Thanks in advance.
Products Class:
Public Class Product
Private pName As String
Private pDescription As String
Private pPrice As Integer
Private pPath As String
Private pCat As String
'Constructor, uses database to populate properties based on productName
Public Sub New(ByVal productName As String)
Dim data As New Interaction
Dim work As Product
work = data.ReadProduct(productName)
pCat = work.Cat
pName = work.Name
pDescription = work.Description
pPrice = work.Price
End Sub
'Constructor, populates properties from passed in values
Public Sub New(ByVal NameIn As String,
ByVal DescriptionIn As String, ByVal PriceIn As Integer, ByVal CatIn As String, ByVal ImagePathIn As String)
pName = NameIn
pDescription = DescriptionIn
pPrice = PriceIn
pPath = ImagePathIn
pCat = CatIn
End Sub
'Stores name of product
Public ReadOnly Property Name() As String
Get
Return pName
End Get
End Property
'Stores a description of the product
Public ReadOnly Property Description() As String
Get
Return pDescription
End Get
End Property
'Stores the price of the product
Public ReadOnly Property Price() As Integer
Get
Return pPrice
End Get
End Property
'Stores the path to the image associated with this product
Public ReadOnly Property ImagePath() As String
Get
Return pPath
End Get
End Property
'Stores name of product
Public ReadOnly Property Cat() As String
Get
Return pCat
End Get
End Property
End Class
Use this instead
Public Function ReadProduct(ByVal CatIn As String) As List(Of Dictionary(String, Of String))
Dim ReturnProducts As New List(Of Dictionary(String, Of String))
Try
Call GetProduct(CatIn)
Dim dbr As SqlDataReader
' Execute the created SQL command from GetProduct and set to the SqlDataReader object
dbr = cmdSelect.ExecuteReader
Dim FieldCount = dbr.FieldCount()
Dim ColumnList as New List(Of String)
For i as Integer = 0 to FieldCount - 1
ColumnList.Add(dbr.GetName(i))
Next
While dbr.Read()
Dim ReturnProduct As New Dictionary(String, Of String)
For i as Integer = 0 to FieldCount - 1
ReturnProduct.Add(ColumnList(i), dbr.GetValue(i).toString())
Next
ReturnProducts.Add(ReturnProduct)
End While
cmdSelect.Parameters.Clear()
dbr.Close()
Catch ex As SqlException
Dim strOut As String
strOut = ex.Message
Console.WriteLine(strOut)
End Try
' Return the Product object
Return ReturnProducts
End Function
then, inside printMenuBlock, you declare product with
Dim product = db.ReadProduct(productName)
and later, you access it like so
For i as Integer = 0 to product.Count - 1
'do everything normally for building str except, for example, if you want
'to acccess product.Name as before, access it with product(i).Item("Name"),
'assuming that your column name/alias for "Name" is in fact "Name"
'i personally like to align column names to variable names for laziness's sake
'bad obfuscation practice tho if you don't use aliases
Next

query database with each object in Arraylist and databind to gridview?

I have a function that returns a list of account numbers as an Arraylist. I am trying to use each account as a command parameter in another sub routine to get more data about each account number. This only returns the data for the last account number in the arraylist. I need to use each account number, call the database, get the additional information and store ALL of the data into a Gridview (databind). Example: If I had 3 account numbers in my arraylist return 3 rows of data to the gridview. I am struggling with how to get ALL of the information for each value (account number) in the Arraylist. Can someone point me in the right direction?? I think this can be done but I am not certain if my approach is correct or not. Perhaps I need to create datatables that contain the additional information for each value passed via the arraylist....Any Ideas??
#jwatts1980 thanks for the comment: I will try to clarify. I have an arraylist of account numbers (and maybe this is where I am off track) I am trying to use the values in this ArrayList as command parameters in another call to a different table/file that returns more info on those accounts. I will provide a portion of the code to help clarify what it is I am attempting to do:
Private Function ReturnMultAccts(ByVal strAcct) As ArrayList
Dim acctsDetail As New ArrayList
Dim dsn As String = ConfigurationManager.ConnectionStrings.ConnectionString
Dim sql As String = "SELECT DISTINCT * FROM FILE WHERE ACCTNUM=?"
Using conn As New OdbcConnection(dsn)
Using cmd As New OdbcCommand(sql, conn)
conn.Open()
cmd.Parameters.Add("ACCTNUM", OdbcType.VarChar, 20).Value = strAcct
Dim rdrUsers As OdbcDataReader = cmd.ExecuteReader()
If rdrUsers.HasRows Then
While rdrUsers.Read()
acctsDetail.Add(Trim(rdrUsers.Item("ACCTNUM")))
End While
End If
rdrUsers.Close()
conn.Close()
End Using
End Using
This returns an Arraylist of Account Numbers (Lets say it is 3 acct numbers). I call this Function from another Sub:
Private Sub GetMoreAcctInfo(ByVal strAcct)
'Create New ArrayList
Dim MultAccts As New ArrayList
'Pass strAcct to Function to get Multiples
MultAccts = ReturnMultAccts(strAcct)
'Create the variable BachNum for the loop
Dim BachNum As String = MultAccts.Item(0)
For Each BachNum In MultAccts
'Get All of the necessary info from OtherFile based on the BachNum for BOS's
Dim dsn As String = ConfigurationManager.ConnectionStrings.ConnectionString
Dim sql As String = "SELECT ACCTNUM, BILSALCOD1, BILSALCOD2, BILSALCOD3, OTHACCTNUM FROM OtherFile WHERE OTHACCTNUM=?" 'Equal to the items in the arraylist
Using conn As New OdbcConnection(dsn)
Using cmd As New OdbcCommand(sql, conn)
conn.Open()
cmd.Parameters.Add("OTHACCTNUM", OdbcType.VarChar, 20).Value = BachNum
Using adapter = New OdbcDataAdapter(cmd)
Dim DS As New DataSet()
adapter.Fill(DS)
GridView1.DataSource = DS
GridView1.DataBind()
End Using
End Using
End Using
Next
End Sub
Hopefully this clarifies what I am attempting to do...??
To elaborate on my suggestion, you will need a list of strongly typed objects. You can add those items to the list, then bind the list to the GridView.
I'll start at the beginning. You know what kind of data is coming from your database: ACCTNUM, BILSALCOD1, BILSALCOD2, BILSALCOD3, and OTHACCTNUM. So you can use those to create an object.
Friend Class AccountClass
Private pACCTNUM As string = ""
Private pBILSALCOD1 As string = ""
Private pBILSALCOD2 As string = ""
Private pBILSALCOD3 As string = ""
Private pOTHACCTNUM As string = ""
Public Property ACCTNUM() As string
Get
Return pACCTNUM
End Get
Set(ByVal value as string)
Me.pACCTNUM = value
End Set
End Property
Public Property BILSALCOD1() As string
Get
Return pBILSALCOD1
End Get
Set(ByVal value as string)
Me.pBILSALCOD1 = value
End Set
End Property
Public Property BILSALCOD2() As string
Get
Return pBILSALCOD2
End Get
Set(ByVal value as string)
Me.pBILSALCOD2 = value
End Set
End Property
Public Property BILSALCOD3() As string
Get
Return pBILSALCOD3
End Get
Set(ByVal value as string)
Me.pBILSALCOD3 = value
End Set
End Property
Public Property OTHACCTNUM() As string
Get
Return pOTHACCTNUM
End Get
Set(ByVal value as string)
Me.pOTHACCTNUM = value
End Set
End Property
Sub New(ByVal ACCTNUM As string, ByVal BILSALCOD1 As string, ByVal BILSALCOD2 As string, ByVal BILSALCOD3 As string, ByVal OTHACCTNUM As string)
Me.ACCTNUM = ACCTNUM
Me.BILSALCOD1 = BILSALCOD1
Me.BILSALCOD2 = BILSALCOD2
Me.BILSALCOD3 = BILSALCOD3
Me.OTHACCTNUM = OTHACCTNUM
End Sub
End Class
Then you rework the GetMoreAcctInfo() routine to use it.
Private Sub GetMoreAcctInfo(ByVal strAcct)
'Create New ArrayList
Dim MultAccts As ArrayList
'Pass strAcct to Function to get Multiples
MultAccts = ReturnMultAccts(strAcct)
'Create the variable BachNum for the loop
Dim BachNum As String
'Create the list to bind to the grid
Dim AcctInfo As New Generic.List(Of AccountClass)
'create the dataset
Dim DS As DataSet
For Each BachNum In MultAccts
'Get All of the necessary info from OtherFile based on the BachNum for BOS's
Dim dsn As String = ConfigurationManager.ConnectionStrings.ConnectionString
Dim sql As String = "SELECT ACCTNUM, BILSALCOD1, BILSALCOD2, BILSALCOD3, OTHACCTNUM FROM OtherFile WHERE OTHACCTNUM=?" 'Equal to the items in the arraylist
Using conn As New OdbcConnection(dsn)
Using cmd As New OdbcCommand(sql, conn)
conn.Open()
cmd.Parameters.Add("OTHACCTNUM", OdbcType.VarChar, 20).Value = BachNum
Using adapter = New OdbcDataAdapter(cmd)
DS = New DataSet()
adapter.Fill(DS)
For Each t As DataTable In DS.Tables
For Each r As DataRow In t.Rows
AcctInfo.Add(new AccountClass(r("ACCTNUM"), r("BILSALCOD1"), r("BILSALCOD2"), r("BILSALCOD3"), r("OTHACCTNUM")))
Next
Next
End Using
End Using
End Using
Next
GridView1.DataSource = AcctInfo
GridView1.DataBind()
End Sub