Writing complex database queries in VB can be quite taxing. Often creating a Stored Procedure in MSSQL, or even better, accessing one that has already been created for you is a great solution to avoid the hassle. In another scenario, multple applications that perform the same queries can utilize Stored Procedures to enhance efficiency and centralize data management. This example will show how to do this using either ODBC or a SQL connection
Mi-Forms is known for it's flexibility, and it's ability to access stored procedures is no exception. All you need to get started is a database with a stored procedure. I won't go into detail about how to build a stored procedure here.
The example I will use here works with the AdventureWorks2012 sample database supplied by Microsoft. Once you install this database onto an MSSQL Server, you can navigate to the stored procedures to view them as shown in the following image.
For simplicity, we will be accessing the uspGetEMployeeManagers stored procedure, because it only requires one parameter to return results.
If using ODBC for your connection type, create the Odbc connection.
In the Mi-Forms Designer, we created a Picklist to show the business entity ids and and a Grid to display the data returned by the stored procedure.
Because this database uses a complex schema structure, we populate the static Picklist using a .NET scripted method. I chose to use ODBC for this example. You may note that the SELECT statement is limiting the return results to the first 100. This is because there are over 20,000 entries in AdventureWorks2012.
<MiCode(FormScriptEventType.AfterOpen)> _
Public Sub Form_AfterOpen(ByVal e As AfterOpenEventArgs)
' Fill _BusinessEntity Picklist values from Person.BusinessEntity table in AdventureWorks2012
Dim connectionString As String = "DRIVER={SQL Server};DSN=AdventureWorks2012;Server=KEVIN\SQLEXPRESS;Database=AdventureWorks2012;Uid=mf;Pwd=pass;"
Dim connection As New OdbcConnection(connectionString)
Dim cmd As String = "SELECT BusinessEntityID FROM Person.BusinessEntity WHERE BusinessEntityID < 99"
Dim adapter As New OdbcDataAdapter(cmd, connection)
Dim dt As New Datatable
adapter.Fill(dt)
Dim list As New ArrayList
' Populate picklist
For Each row As DataRow In dt.Rows
_BusinessEntitySql.AddItem(row(0))
_BusinessEntityOdbc.AddItem(row(0))
Next
End Sub
The Picklist uses its AfterSetData method to call the stored procedure call. It uses a single parameter, but is designed such that you can add multiple parameters.
<MiCode(ControlScriptEventType.AfterSetData, "BusinessEntityOdbc")> _
Public Sub Ctl_BusinessEntityOdbc_AfterSetData(ByVal e As AfterSetDataEventArgs)
' odbc connection method
Dim cmd As New OdbcCommand("{call uspGetEmployeeManagers (?)}")
cmd.Parameters.Add("@BusinessEntityID", OdBcType.Int).Value = _BusinessEntityOdbc.Value
Dim dt As DataTable = ExecuteOdBcCMD(cmd).Tables(0)
' Populate grid
_EmployeeManagers.Value = dt
End Sub
Function ExecuteOdBcCMD(ByRef cmd As OdBcCommand) As DataSet
Dim connectionString As String = "DRIVER={SQL Server};DSN=AdventureWorks2012;Server=KEVIN\SQLEXPRESS;Database=AdventureWorks2012;Uid=mf;Pwd=pass;"
Dim ds As New DataSet()
Try
Dim connection As New OdBcConnection(connectionString)
cmd.Connection = connection
cmd.CommandType = CommandType.StoredProcedure
Dim adapter As New OdBcDataAdapter(cmd)
adapter.SelectCommand.CommandTimeout = 300
'fill the dataset
adapter.Fill(ds)
connection.Close()
Catch ex As Exception
' The connection failed. Display an error message.
MsgBox("Database Error: " & ex.Message)
End Try
Return ds
End Function
Adding multiple parameters to this query in the AfterSetData method could look like the following.
Dim cmd As New OdbcCommand("{? = call newStoredProcedure (?,?,?)}")
cmd.Parameters.Add("@Parameter1", OdBcType.Int).Value = 1
cmd.Parameters.Add("@Parameter2", OdBcType.Text).Value = "Parameter2Value"
cmd.Parameters.Add("@Parameter3", OdBcType.Text).Value = "Parameter3Value"
Upon change of the picklist value the grid will populate with the returned data from the stored procedure.
Similarly, you can create this using a standard SQL connection, but there are some minor changes so I will include that code below as well.
<MiCode(ControlScriptEventType.AfterSetData, "BusinessEntitySql")> _
Public Sub Ctl_BusinessEntity_AfterSetData(ByVal e As AfterSetDataEventArgs)
' sql connection method
Dim cmd As New SqlCommand("uspGetEmployeeManagers")
cmd.Parameters.Add("@BusinessEntityID", SqlDbType.Int).Value = _BusinessEntitySql.Value
Dim dt As DataTable = ExecuteCMD(cmd).Tables(0)
' Populate grid
_EmployeeManagers.Value = dt
End Sub
Function ExecuteCMD(ByRef CMD As SqlCommand) As DataSet
Dim connectionString As String = "Server=KEVIN\SQLEXPRESS;Database=AdventureWorks2012;Uid=mf;Pwd=pass;"
Dim ds As New DataSet()
Try
Dim connection As New SqlConnection(connectionString)
cmd.Connection = connection
cmd.CommandType = CommandType.StoredProcedure
Dim adapter As New SqlDataAdapter(cmd)
adapter.SelectCommand.CommandTimeout = 300
'fill the dataset
adapter.Fill(ds)
connection.Close()
Catch ex As Exception
' The connection failed. Display an error message.
MsgBox("Database Error: " & ex.Message)
End Try
Return ds
End Function
You can download the working version of this form from the link below. Keep in mind that you will need to install the AdventureWorks12012 database, either add a new user with user/pass of mf/pass or modify those in the connection string, and create the ODBC connection (be sure to use ODBC32).