vb.net return json object with multiple types? - sql

I need to return some data from a web service that looks something like this:
data.page = 1
data.count = 12883
data.rows(0).id = 1
data.rows(0).name = "bob"
data.rows(1).id = 2
data.rows(1).name = "steve"
data.rows(2).id = 3
data.rows(2).name = "fred"
I have no idea how to do this. I've returend simple types and simple arrays, but never an object like this.
The data source is a sql Database. The target is a javascript/ajax function. I'm currently successfully returning the rows themselves as a dataset and it works, but I need to add the count and a couple other "parent level" variables.
For the sake of full disclosure, here is the code that is working:
<WebMethod()> _
Public Function rptPendingServerRequests() As DataSet
Dim connetionString As String
Dim connection As SqlConnection
Dim command As SqlCommand
Dim adapter As New SqlDataAdapter
Dim ds As New DataSet
Dim sql As String
connetionString = "..."
sql = "SELECT usm_request.request_id, usm_request.status, usm_request.req_by_user_id " +
"FROM usm_request " +
"WHERE usm_request.request_id in " +
"(SELECT distinct(usm_request.request_id) from usm_request, usm_subscription_detail WHERE usm_request.request_id = usm_subscription_detail.request_id " +
"AND usm_subscription_detail.offering_id = 10307) ORDER BY usm_request.request_id DESC"
connection = New SqlConnection(connetionString)
Try
connection.Open()
command = New SqlCommand(sql, connection)
adapter.SelectCommand = command
adapter.Fill(ds)
adapter.Dispose()
command.Dispose()
connection.Close()
Return ds
Catch ex As Exception
End Try
End Function
And I'm trying to consume it with FlexiGrid. I've been working at it for a few hours with no luck. I basically need to convert the PHP at the following site to .net
http://code.google.com/p/flexigrid/wiki/TutorialPropertiesAndDocumentation

I think that you would be much better off just creating a couple of classes and moving the data from the database into these classes. For example:
Public Class MyDataClass
Public Property Page As Integer
Public ReadOnly Property Count As Integer
Get
If Me.Rows IsNot Nothing Then
Return Me.Rows.Count
Else
Return 0
End If
End Get
End Property
Public Property Rows As List(Of MyDataRow)
' Parameterless constructor to support serialization.
Public Sub New()
Me.Rows = New List(Of MyDataRow)
End Sub
Public Sub New(wPage As Integer, ds As DataSet)
Me.New()
Me.Page = wPage
For Each oRow As DataRow In ds.Tables(0).Rows
Dim oMyRow As New MyDataRow
oMyRow.Id = oRow("id")
oMyRow.Name = oRow("Name")
Me.Rows.Add(oMyRow)
Next
End Sub
End Class
Public Class MyDataRow
Public Property Id As Integer
Public Property Name As String
' Parameterless constructor to support serialization
Public Sub New()
End Sub
End Class
Then change the return type of the method to MyDataClass and change the return to:
Return New MyDataClass(1, ds)

Related

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

Problem with my VB2005-MSAccess Connection

I am using MS Access as a database, but the error occurs in column Abstract.
Error message:
Column 'Abstract' does not belong to table tblBooks
This column is actually included in the table but I'm not sure if the problem is its DataType.(Memo)
Is it possible to use this field with Memo datatype? Is there any error with my code (using my module)?
My code:
Module Module1
Public MyConn As New OdbcConnection("Dsn=MS Access Database;dbq=D:\MyPrograms\VB.Net\Library System\dblibrary.mdb;defaultdir=D:\MyPrograms\VB.Net\Library System;driverid=25;fil=MS Access;maxbuffersize=2048;pagetimeout=5;uid=admin")
Public MyComm As New OdbcCommand
Public MyTable As New DataSet
Public MyAdapt As New OdbcDataAdapter
Public Counter As Integer
Function Adapt(ByVal MyCommand As String, ByVal MyDataSet As String) As String
MyAdapt = New OdbcDataAdapter(MyCommand, MyConn)
MyAdapt.Fill(MyTable, MyDataSet)
Return 0
End Function
End Module
Private Sub Search()
If cmbCategoryFilter.SelectedItem = "All" Then
Adapt("select * from tblBooks", "tblBooks")
txtISBNInfo.Text = MyTable.Tables(0).Rows(Counter)("ISBN").ToString
txtTitleInfo.Text = MyTable.Tables(0).Rows(Counter)("Title").ToString
txtAuthorInfo.Text = MyTable.Tables(0).Rows(Counter)("Author").ToString
txtAbstractInfo.Text = MyTable.Tables(0).Rows(Counter)("Abstract").ToString
End If
End Sub

Problem Understanding Access Modifiers in VB.Net with List( Of Object)

I've recently been updating a lot of my code to comply with proper n-tier architecture and OO programming, following examples from a book.
I'm starting to get problems now because I don't fully understand the access modifiers.
If I run the following code I get an error at the line
Dim clientFamilyDataAccessLayer As New ClientFamilyDAO
in the BLL at the point it creates an instance of the DAL. The full error message is: "The type initializer for 'ClientFamilyDAO' threw an exception. ---> System.NullReferenceException: Object reference not set to an instance of an object."
How do I use these function to create a list of ClientFamily objects that I can then work with?
On my UI layer I'm creating a list of objects; ClientFamilies
Dim listOfClientFamilies As List(Of ClientFamily) = ClientFamily.GetClientFamiliesByKRM(selectedEmployee.StaffNumber)
This is the function in the BLL
Public Shared Function GetClientFamiliesByKRM(ByVal krmStaffNumber As Integer) As List(Of ClientFamily)
Dim clientFamilyDataAccessLayer As New ClientFamilyDAO
Return clientFamilyDataAccessLayer.GetClientFamiliesByKRM(krmStaffNumber)
End Function
and this is function in the DAL
Public Function GetClientFamiliesByKRM(ByVal staffNumber As Integer) As List(Of ClientFamily)
Dim currentConnection As SqlConnection = New SqlConnection(_connectionString)
Dim currentCommand As New SqlCommand
currentCommand.CommandText = mainSelectStatement & " WHERE Key_Relationship_Manager = #StaffNumber ORDER BY Client_Family_Name"
currentCommand.Parameters.AddWithValue("#StaffNumber", staffNumber)
currentCommand.Connection = currentConnection
Dim listOfClientFamilies As New List(Of ClientFamily)
Using currentConnection
currentConnection.Open()
Dim currentDataReader As SqlDataReader = currentCommand.ExecuteReader()
Do While currentDataReader.Read
Dim newClientFamily As AECOM.ClientFamily = PopulateClientFamily(currentDataReader)
listOfClientFamilies.Add(newClientFamily)
Loop
End Using
Return listOfClientFamilies
End Function
Here's the full ClientFamilyDAO Class:
Public Class ClientFamilyDAO
Private Const mainSelectStatement As String = "SELECT Client_Family_ID, Client_Family_Name, Key_Relationship_Organisation, Key_Relationship_Manager, Obsolete, Market_Sector_ID FROM Client_Families"
Private Shared ReadOnly _connectionString As String = String.Empty
Shared Sub New()
_connectionString = WebConfigurationManager.ConnectionStrings("ClientFamilyManagementConnectionString").ConnectionString
End Sub
Public Function GetClientFamiliesByKRM(ByVal staffNumber As Integer) As List(Of ClientFamily)
Dim currentConnection As SqlConnection = New SqlConnection(_connectionString)
Dim currentCommand As New SqlCommand
currentCommand.CommandText = mainSelectStatement & " WHERE Key_Relationship_Manager = #StaffNumber ORDER BY Client_Family_Name"
currentCommand.Parameters.AddWithValue("#StaffNumber", staffNumber)
currentCommand.Connection = currentConnection
Dim listOfClientFamilies As New List(Of ClientFamily)
Using currentConnection
currentConnection.Open()
Dim currentDataReader As SqlDataReader = currentCommand.ExecuteReader()
Do While currentDataReader.Read
Dim newClientFamily As AECOM.ClientFamily = PopulateClientFamily(currentDataReader)
listOfClientFamilies.Add(newClientFamily)
Loop
End Using
Return listOfClientFamilies
End Function
Private Function PopulateClientFamily(ByVal currentDataReader As SqlDataReader) As AECOM.ClientFamily
Dim newClientFamily As New AECOM.ClientFamily
If Not (currentDataReader.IsDBNull(currentDataReader.GetOrdinal("Client_Family_ID"))) Then
newClientFamily.ClientFamilyID = currentDataReader("Client_Family_ID")
End If
If Not (currentDataReader.IsDBNull(currentDataReader.GetOrdinal("Client_Family_Name"))) Then
newClientFamily.ClientFamilyName = currentDataReader("Client_Family_Name")
End If
If Not (currentDataReader.IsDBNull(currentDataReader.GetOrdinal("Key_Relationship_Organisation"))) Then
Select Case currentDataReader("Key_Relationship_Organisation")
Case False
newClientFamily.IsKeyRelationshipOrganisation = False
Case True
newClientFamily.IsKeyRelationshipOrganisation = True
End Select
End If
If Not (currentDataReader.IsDBNull(currentDataReader.GetOrdinal("Key_Relationship_Manager"))) Then
newClientFamily.KeyRelationshipManagerStaffNumber = currentDataReader("Key_Relationship_Manager")
End If
If Not (currentDataReader.IsDBNull(currentDataReader.GetOrdinal("Obsolete"))) Then
Select Case currentDataReader("Obsolete")
Case False
newClientFamily.Obsolete = False
Case True
newClientFamily.Obsolete = True
End Select
End If
If Not (currentDataReader.IsDBNull(currentDataReader.GetOrdinal("Market_Sector_ID"))) Then
newClientFamily.MarketSectorID = currentDataReader("Market_Sector_ID")
End If
Return newClientFamily
End Function
End Class
The issue doesn't relate to access modifiers, rather it is more to do with the exception message you get. The following line within the constructor of ClientFamilyDAO would seem to be causing the issue:
_connectionString = WebConfigurationManager.ConnectionStrings("ClientFamilyManagementConnectionString").ConnectionString
Are you sure ClientFamilyManagementConnectionString exists in the configuration?