WCF List Parameters - vb.net

I'm trying to pass a list of objects to my WCF service, but it doesn't seem I can pass an object list from my console test application. I have an error that states:
Value of type
'System.Collections.Generic.List(Of
ConsoleTestingApp.ServiceReference1.LetterVariables)'
cannot be converted to '1-dimensional
array of
ConsoleTestingApp.ServiceReference1.LetterVariables'.
On this line:
Console.WriteLine(client.GetLetterObj("1", "1", "0", lstVariables))
Anybody have any ideas what I need to do?
Thanks,
Jason
'******* Code ***********
My test console app looks like this:
Dim Variables As LetterVariables
Dim lstVariables As New List(Of LetterVariables)
Variables = New LetterVariables
Variables._Sort = 10
Variables._key = "Letter Number"
Variables._value = "10"
lstVariables.Add(Variables)
Variables = New LetterVariables
Variables._Sort = 20
Variables._key = "Amount"
Variables._value = "$200"
lstVariables.Add(Variables)
Console.WriteLine(client.GetLetterObj("1", "1", "0", lstVariables))
Console.WriteLine("Finished")
Here's the contract:
<OperationContract()> _
Function GetLetterVariablesObj(ByVal LetterSpecID As Int32) As List(Of LetterVariables)
Here's the svc:
Public Function GetLetterObj(ByVal LetterID As String, ByVal StateID As String, ByVal CompID As String, ByVal lstVars As System.Collections.Generic.List(Of LetterVariables)) As String Implements ILetterWriter.GetLetterObj
Dim SQLcon As New SqlClient.SqlConnection
Dim SQLcmd As New SqlClient.SqlCommand
Dim Variables As LetterVariables
Dim tblVars As DataTable
'Load the datatable to be passed to SQL Server
tblVars = New DataTable
tblVars.TableName = "LetterVariables"
tblVars.Columns.Add("Order")
tblVars.Columns.Add("Key")
tblVars.Columns.Add("Value")
For Each Variables In lstVars
tblVars.Rows.Add(Variables.Sort, Variables.Key, Variables.Value)
Next
'Connect to the database
SQLcon.ConnectionString = "Data Source=MySRVR;Initial Catalog=Sears;User ID=me;Password=mypass;"
SQLcon.Open()
'Set the procedure name, type & connection
SQLcmd.CommandText = "sp_cmd"
SQLcmd.CommandType = CommandType.StoredProcedure
SQLcmd.Connection = SQLcon
'Pass the parameters
SQLcmd.Parameters.AddWithValue("#LetterID", LetterID)
SQLcmd.Parameters.AddWithValue("#StateID", StateID)
SQLcmd.Parameters.AddWithValue("#CompID", CompID)
SQLcmd.Parameters.AddWithValue("#Vars", tblVars)
'Initialize the function string, execute the stored procedure
GetLetterObj = ""
GetLetterObj = SQLcmd.ExecuteScalar
'Close it all down
SQLcon.Close()
SQLcon.Dispose()
SQLcmd.Dispose()
End Function

This is because Collections are exposed as arrays by default. You should be able to pass in lstVariables.ToArray(). See this post for the explanation as to why it is the way it is.

Related

Issues on loop for retrieve the dynamic sql parameter values from dynamic textboxes

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

How to factorize calls to ado.net with parameters?

i want to factorize all the calls to ado.net present in my web application to not repeat over and over the connection string and the open/close methods. I succeed to do it for the calls without parameter, but i need help for the ones with parameters.
For example, I had :
Dim strConnexion As String = "myConnectionString"
Dim strRequete As String = "DELETE FROM tbl_devis WHERE id_devis = " + TBDevis.Text
Dim oConnection As New SqlConnection(strConnexion)
Dim oCommand As New SqlCommand(strRequete, oConnection)
oConnection.Open()
oConnection.ExecuteNonQuery()
oConnection.Close()
I factorized it into :
ExecuteRequest("DELETE FROM tbl_devis WHERE id_devis = " + TBDevis.Text)
And the code of ExecuteRequest :
Public Shared Sub ExecuteRequest(ByVal strRequest As String)
Dim strConnection As String = ChaineDeConnexion()
Using objConnection = New SqlConnection(strConnection)
Dim objCommand As SqlCommand
objCommand = New SqlCommand(strRequest, objConnection)
objCommand.Connection.Open()
objCommand.ExecuteNonQuery()
End Using
End Sub
But I would like be able to pass to Execute request a collection of parameters. This is a very simple example of what kind of code I want to factorize :
Dim strConnexion As String = "myConnectionString"
Dim strRequete As String = "DELETE FROM tbl_devis WHERE id_devis = #id_devis"
Dim oConnection As New SqlConnection(strConnexion)
Dim oCommand As New SqlCommand(strRequete, oConnection)
With (myCommand.Parameters)
.Add(New SqlParameter("#id_devis", SqlDbType.Int))
End With
With myCommand
.Parameters("#id_devis").Value = TBDevis.Text
End With
oConnection.Open()
oConnection.ExecuteNonQuery()
oConnection.Close()
I was thinking about edit my ExecuteRequest function to add an optional parameters collection :
Public Shared Sub ExecuteRequest(ByVal strRequest As String, Optional ByRef sqlParameters As SqlParameterCollection = Nothing)
Dim strConnection As String = ChaineDeConnexion()
Using objConnection = New SqlConnection(strConnection)
Dim objCommand As SqlCommand
objCommand = New SqlCommand(strRequest, objConnection)
objCommand.Parameters = sqlParameters 'objCommand.Parameters is readonly property
objCommand.Connection.Open()
objCommand.ExecuteNonQuery()
End Using
End Sub
But VS tell me that objCommand.Parameters is a readonly property...
I see two solutions :
Passing an array containing the parameter name, value and type, and looping through the array
Creating the string request with all the parameters like that : "DELETE FROM tbl_devis WHERE id_devis = " + TBDevis.Text ... but when there are 30 parameters, this is a dirty solution I guess ?
Which one would be the cleaner, strongest solution please ?
Thanks for your help !
ParamArray is what you're looking for.
Update your ExecuteRequest like this:
Public Sub ExecuteRequest(ByVal strRequest As String, ParamArray Params() As SqlParameter)
Dim strConnexion As String = "myConnectionString"
Using Conn As New SqlConnection(strConnexion), Cmd As New SqlCommand(strRequest, Conn)
Cmd.Parameters.AddRange(Params)
Conn.Open()
Cmd.ExecuteNonQuery()
End Using
End Sub
and then you can call it like
ExecuteRequest("DELETE FROM tbl_devis WHERE id_devis = #id_devis", New SqlParameter("#id_devis", CInt(TBDevis.Text)))
I would also suggest to create function sqlPar(Name As String, Value As Object) with few more overloads to simplify the call to
ExecuteRequest("DELETE FROM tbl_devis WHERE id_devis = #id_devis", sqlPar("#id_devis", TBDevis.Text))
ParamArray allows you to add undefined amount of arguments like this
ExecuteRequest("SELECT ID FROM Table WHERE ID IN (#A, #B, #C, #D)", sqlPar("#A", 1), sqlPar("#B", 2), sqlPar("#C", 3), sqlPar("#D", 4))
You should ALWAYS use SqlParameter instead of string concatenation to prevent SQL injections.
You should ALWAYS use Using for IDisposable resources as well.

Identify the properties of an object and put values into it

I want to identify the properties of specific object that it receives when the method is called and put values in it from the db result that I got. I've searched about it but I'm currently stucked in how I should proceed from here. Here is my code..
Public Class DBModel
Public Sub getFromDB(ByRef lists As List(Of Object), ByVal classType As Type, ByVal tblName as String)
Dim strSql As String = "SELECT * FROM " & tblName
Dim props = classType.GetProperties()
Try
Using cnn As New SqlConnection("Data Source = .\; Initial Catalog = DBName;" & "Integrated Security = True;")
Using cmd As New SqlCommand(strSql, cnn)
cnn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader()
While dr.Read
For Each prop In props
For i As Integer = 0 To dr.VisibleFieldCount - 1
prop = dr.GetValue(i)
Next
Next
lists.Add(props)
End While
End Using
End Using
End Using
Catch e As Exception
MessageBox.Show(e.ToString())
End Try
End Sub
End Class
I'm calling here the getFromDB method to populate the list of customers in this class, but I'll also call the getFromDB method from other classes with another different set of properties..
Public Class CustomerCtrler
private _CustomerList As New List(Of Customer)
Public Sub New()
Dim dbModel As New DBModel
Dim cust As New Customer
dbModel.getFromDB(_CustomerList, cust.GetType, "CustTbl")
End sub
End Class
Public Class Customer
Public Property custID As Integer
Public Property FirstName As String
Public Property LastName As String
Public Property DateRegistered As DateTime
End Class
But I got a InvalidCastException, so I've searched about converting the data types but I got: "Value type of Integer cannot be converted into PropertyInfo" at the 'prop = dr.GetValue(i)' line..
I'm quite new to object oriented programming so I'm sorry if there's a lot of mistakes there but your help will be really appreciated..
I would tend to go with something like this:
Public Function GetListFromDatabase(Of T As New)(tableName As String) As List(Of T)
Dim itemType = GetType(T)
Dim allProperties = itemType.GetProperties()
Dim items As New List(Of T)
Using connection As New SqlConnection("connection string here"),
command As New SqlCommand($"SELECT * FROM [{tableName}]", connection)
connection.Open()
Using reader = command.ExecuteReader()
Dim columnNames = reader.GetColumnSchema().
Select(Function(column) column.ColumnName).
ToArray()
'Ignore properties that don't have a corresponding column.
Dim properties = allProperties.Where(Function(prop) columnNames.Contains(prop.Name)).
ToArray()
Do While reader.Read()
'We can do this because we have specified that T must have a
'parameterless constructor by using "As New" in the method declaration.
Dim item As New T
For Each prop In properties
prop.SetValue(item, reader(prop.Name))
Next
items.Add(item)
Loop
End Using
End Using
Return items
End Function
You can then do this:
_CustomerList = dbModel.GetListFromDatabase(Of Customer)("CustTbl")
You can obviously create a variation on that if you really want to pass in an existing list but I don't see the point in that unless the list might already contain items.
EDIT: Here is an alternative method to get the data reader column names. I haven't tested it so it may be that "COLUMN_NAME" isn't quite right but it will be something very close to this:
Dim schemaTable = reader.GetSchemaTable()
Dim columnNames = schemaTable.Rows.
Cast(Of DataRow).
Select(Function(row) CStr(row("COLUMN_NAME"))).
ToArray()

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.

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