Data Access Layer Populate Combobox With Parameters - vb.net

I am using VB.Net (Visual Studio 2013) and N-tier architecture to populate a combo box list. My code for the class is as below
Public Shared Function List() As List(Of AppName.BusinessLogic.BLL_RMCodeComboClass)
Dim dbo_RMCodeList As New List(Of AppName.BusinessLogic.BLL_RMCodeComboClass)
Dim connTemp As SqlConnection = AppClass.GetConnection
Dim strSelectSQL As String = "SELECT [RMCode] FROM [dbo].[RMMaster] WHERE [dbo].[RMMaster].[Category] = '" & strRMType & "'"
Dim strCommandSelect As New SqlCommand(strSelectSQL, connTemp)
Try
connTemp.Open()
Dim rdrTemp As SqlDataReader = strCommandSelect.ExecuteReader()
Dim clsdbo_RMCodeList As AppName.BusinessLogic.BLL_RMCodeComboClass
Do While rdrTemp.Read
clsdbo_RMCodeList = New BusinessLogic.BLL_RMCodeComboClass
clsdbo_RMCodeList.RMCode = System.Convert.ToString(rdrTemp("RMCode").ToString)
dbo_RMCodeList.Add(clsdbo_RMCodeList)
Loop
rdrTemp.Close()
Catch ex As SqlException
Throw ex
Finally
connTemp.Close()
End Try
Return dbo_RMCodeList
End Function
My objective is to retrieve or populate the combobox with RMCodes depending upon the type. Hence I have used the strSelectSQL accordingly. Please help me to pass the value of the Category to this function so that it becomes dynamic. The value of the Type is selected from another combo box on the presentation/UI layer and as such the Code field should be populated according to the Category chosen.
Thanks in advance
CL

E.g.
Private Function List(type As String) As List(Of Thing)
'...
Dim command As New SqlCommand("SELECT * FROM MyTable WHERE #Type IS NULL OR Type = #Type")
command.Parameters.Add("#Type",
SqlDbType.NVarChar,
50).Value = If(String.IsNullOrEmpty(type),
CObj(DBNull.Value),
type)
'...
End Function
That makes the filter optional. If you pass in Nothing or an empty String then the SQL parameter is NULL and every record matches, otherwise the result set is filtered by the value you pass in.

Related

Must declare the scalar variable "#SSTGroupID"

Private Function GetSvcType(ByVal oCommand As OleDbCommand, ByVal SSTGroupID As Integer) As DataTable
Dim sSQL As New StringBuilder
sSQL.AppendLine(" Select SSTServiceTypeID AS ID, SSTServiceTypeName AS Name ")
sSQL.AppendLine(" from fgen_SSTServiceType (nolock) ")
sSQL.AppendLine(" Where 1=1 AND Disabled = 0 ")
sSQL.AppendLine(" AND fgen_SSTServiceType.SSTGroupID = #SSTGroupID ")
oCommand.Parameters.AddWithValue("#SSTGroupID", SSTGroupID)
Return GetDataTable(sSQL.ToString)
End Function
Private Function GetDataTable(ByVal SQL As String) As DataTable
Dim oConn As OleDbConnection = New OleDbConnection(_strConnection)
Dim oCommand As New OleDbCommand("", oConn)
oCommand.Connection.Open()
oCommand.CommandText = SQL
oCommand.Parameters.Clear()
Dim oDataTable As New DataTable
Dim oDataAdapter As New OleDbDataAdapter(oCommand)
oDataAdapter.Fill(oDataTable)
If oDataTable.Rows.Count > 0 Then
GetDataTable = oDataTable
Else
GetDataTable = Nothing
End If
oCommand.Connection.Close()
oCommand.Dispose()
End Function
I've been searching for hours on end and can't seem to find a solution. I need your help please thanks
I've updated my question include the GetDataTable function. Please take a look thanks.
Your command never gets the text from the StringBuilder. So I think the missing link is that you should assign the string you've built to the command text
oCommand.CommandText = sSQL.ToString()
then add the parameter after that
Private Function GetSvcType(ByVal oCommand As OleDbCommand, ByVal SSTGroupID As Integer) As DataTable
Dim sSQL As New StringBuilder()
sSQL.AppendLine(" Select SSTServiceTypeID AS ID, SSTServiceTypeName AS Name ")
sSQL.AppendLine(" from fgen_SSTServiceType (nolock) ")
sSQL.AppendLine(" Where 1=1 AND Disabled = 0 ")
sSQL.AppendLine(" AND fgen_SSTServiceType.SSTGroupID = #SSTGroupID ")
oCommand.CommandText = sSQL.ToString()
oCommand.Parameters.AddWithValue("#SSTGroupID", SSTGroupID)
Return GetDataTable(oCommand.CommandText)
End Function
Alternatively, you may want to use a Using to create a command and dispose it. I'd write it but I don't see your connection so you should look into this answer for an example.
I wasn't sure what the Where 1 = 1 and the (no lock) were doing so I removed them.
The function FillDataTable contains all your database access code which keeps it separate from the User Interface code. Your database objects should be locale so you can control that they are closed and disposed. The Using...End Using block takes care of this even if there is an error. Get rid of any class level variables for commands and connections. Both the command and connection are included; note the comma at the end if the first line of the Using.
You can pass your connection string directly to the constructor of the connection and pass the command text and connection directly to the constructor of the command. Saves having to set these properties individually.
OleDb pays no attention to the name of the parameter, so, the order that the parameter is added to the Parameters collection must match the order that the parameter appears in the command text. In this case, you have only one but just for future reference. It is better to use the Parameters.Add() which includes the database datatype. See http://www.dbdelta.com/addwithvalue-is-evil/
and
https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
and another one:
https://dba.stackexchange.com/questions/195937/addwithvalue-performance-and-plan-cache-implications
Here is another
https://andrevdm.blogspot.com/2010/12/parameterised-queriesdont-use.html
Note: I had to guess at the datatype of your parameter. Check your database for the actual type.
Always open your connection at the last possible moment (the line before the .Execute...) and close it as soon as possible (the End Using)
Private Function FillDataTable(GroupID As Long) As DataTable
Dim strSQL = "Select SSTServiceTypeID AS ID, SSTServiceTypeName As Name
From fgen_SSTServiceType
Where Disabled = 0
And SSTGroupID = #SSTGroupID "
Dim dt As New DataTable
Using cn As New OleDbConnection("Your connection string"),
cmd As New OleDbCommand(strSQL, cn)
cmd.Parameters.Add("#SSTGroupID", OleDbType.BigInt).Value = GroupID
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim dt = FillDataTable(7L) 'the L indicates that this is a long,pass the GroupID to the function
DataGridView1.DataSource = dt
End Sub
EDIT
Dim dt = FillDataTable(7L) 'In the button code
And in the Data Access code change Oledb to Sql
Imports System.Data.SqlClient
Class DataAccess
Private Function FillDataTable(GroupID As Long) As DataTable
Dim strSQL = "Select SSTServiceTypeID AS ID, SSTServiceTypeName As Name
From fgen_SSTServiceType
Where Disabled = 0
And SSTGroupID = #SSTGroupID "
Dim dt As New DataTable
Using cn As New SqlConnection("Your connection string"),
cmd As New SqlCommand(strSQL, cn)
cmd.Parameters.Add("#SSTGroupID", SqlDbType.BigInt).Value = GroupID
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
Return dt
End Function
End Class

Converting VBA function to VB.net to get sql data

I am trying to convert VBA code into VB.net and I have made it to a point but I can't convert resultset into vb.net. RS was 'dim as resultset' in VBA, thought i could just change it to dataset but am getting errors with the '.fields' and other options?
Function GetG(sDB As String, sServ As String, sJob As String) As String
'sDB = Database name, sServ = Server\Instance, path = job.path
Dim conString As String = ("driver={SQL Server};server = " &
TextBox1.Text & " ; uid = username;pwd=password:database = " &
TextBox2.Text)
Dim RS As DataSet
Dim conn As SqlConnection = New SqlConnection(conString)
Dim cmd As SqlCommand
conn.Open()
'This is where my problems are occuring
cmd = New SqlCommand("SELECT [ID],[Name] FROM dbo.PropertyTypes")
Do While Not RS.Tables(0).Rows.Count = 0
If RS.Fields(1).Value = sJob Then
GetG = RS.Fields(0).Value
GetG = Mid(GetG, 2, 36)
Exit Do
End If
DataSet.MoveNext
Loop
conn.Close
End Function
Based on my understanding and some guesswork, here is what I came up with for what I think you're wanting.
As I stated in my comment above, it appears you can just use a WHERE clause to get the exact record you want (assuming a single instance of sJob appears in the name column).
Build the connectionstring off the input arguments, not controls on your form. That is after all why you allow for arguments to be passed along. Also note that there is a SqlCommandBuilder object that may be of interest. But for now
Function GetG(sDB As String, sServ As String, sJob As String) As String
'we'll pretend your connectionstring is correct based off of the sDB and sServ arguments
Dim conStr As String = ("driver={SQL Server};server = " & sServ & " ; uid = username;pwd=password:database = " & sDB)
'Create a connection and pass it your conStr
Using con As New SqlConnection(conStr)
con.Open() 'open the connection
'create your sql statement and add the WHERE clause with a parameter for the input argument 'sJob'
Dim sql As String = "SELECT [ID], [Name] FROM dbo.PropertyTypes WHERE [Name] = #job"
'create the sqlCommand (cmd) and pass it your sql statement and connection
Using cmd As New SqlCommand(sql, con)
'add a parameter so the command knows what #job holds
cmd.Parameters.Add(New SqlParameter("#job", SqlDbType.VarChar)).Value = sJob
'Now that have the command built, we can pass it to a reader object
Using rdr As SqlDataReader = cmd.ExecuteReader
rdr.Read()
'i admin i'm a little confused here on what you are
'trying to achieve so ID may not be what you are
'really wanting to get a substring of.
Return rdr("ID").ToString.Substring(2, 36)
End Using
End Using
End Using
End Function
An example to see if this is working could be to call a messagebox do display the result. For this example, I'm going to pretend that TextBox3 holds the sJob you're wanting. With that knowledge, you could simply do:
MessageBox.Show(GetG(TextBox2.Text, TextBox1.Text, TextBox3.Text))
This should then produce the result in a messagebox.
It seems that you're not filling your DataSet. So, when you try to loop through it, it's uninitialized or empty.
Check this answer to see an example: Get Dataset from DataBase

Search records in database for those that match what a user enters

I'm trying to write a function that searches records in my database for the object of those that match the SearchCriteria. The functions parameters look like so:
RetrieveObject(SearchCriteria) As String (SearchCritera is a string aswell)
Right now for testing purposes I am using a console app that asks the user to search by first name.
Console.Writeline("Search by first name: ")
Dim firstName = Console.Readline()
I then use my function: RetrieveObject(firstName)
I want my function to show all the values (lastname, titlename, state, zip) for that particular person that was passed to the RetrieveObject function.
The problem I am having is that I cannot seem to understand how I'm going to match what the user enters with the value in the database.
If anyone could just put me in the right direction to help me understand how to accomplish this, I'd be so grateful!
Here is my code so far:
Private Function RetrieveObject(SearchCriteria As String) As String
Dim cn As OdbcConnection = New OdbcConnection(myCon)
Dim myQuery = "SELECT * FROM Applicant WHERE [strFirstName] LIKE '%son'"
Using com As New OdbcCommand(myQuery)
cn.Open()
com.Connection = cn
com.CommandType = CommandType.Text
com.CommandText = myQuery
com.Parameters.AddWithValue("#strFirstName", SearchCriteria)
Try
com.ExecuteReader()
Catch ex As Exception
MsgBox(ex.Message.ToString())
End Try
End Using
Return SearchCriteria
End Function
Thanks again!
To create a WHERE condition you need to provide (at the most basic level) three informations to the database engine. The first bit is the column name that you want to search for, the second piece is the operator that you want to use for matching records, and finally the value to search for
SELECT * FROM table WHERE FieldName = 'AStringValue'
Of course we could have a lot of variations with operators and field datatype but this answer is limited to your actual situation.
It is important to note that your query could return more than one record (in particular if you add wildcards operators as LIKE, so you cannot simply return a single value with this query, but instead you return a DataTable where you can loop over the Rows collection to see all the records returned by the query
So your code should be changed to
Private Function RetrieveObject(SearchCriteria As String) As DataTable
Dim myQuery = "SELECT * FROM Applicant WHERE [strFirstName] LIKE ?"
Try
Using cn = New OdbcConnection(myCon)
Using da = new OdbcDataAdapter(myQuery, cn)
da.SelectCommand.Parameters.Add("?", OdbcType.VarChar).Value = SearchCriteria
Dim dt = new DataTable()
da.Fill(dt)
return dt
End Using
End Using
Catch ex As Exception
MsgBox(ex.Message.ToString())
return Nothing
End Try
End Function
Now you could call this method with something like
Dim table = RetrieveObject("John%")
if table IsNot Nothing Then
For Each row in table.Rows
Console.WriteLine(row["strFirstName"].ToString())
Next
End If
If you really need to return a json string with all the FirstName matched then you could add this to the last lines of the code above
.....
da.Fill(dt)
Dim names = dt.AsEnumerable().Select(Function(x) x.Field(Of String)("strFirstName")).ToArray()
string output = JsonConvert.SerializeObject(names);
return output;
And of course change again the return value to be a string.
You can also pass your search criteria into function which returns dataset as shown below , one more thing ,you can use the function in textbox textchange event in forms
Also while search include LIKE as LIKE '%" & #strFirstName & "%' which can help you narrow search results if needed
Public Function Search(ByVal Criteria As String) As DataSet
Try
Dim ds As New DataSet
Using sqlCon As New SqlConnection(connStr)
stQuery="SELECT * FROM Applicant WHERE [strFirstName]
LIKE '%" & #strFirstName & "%'"
Dim sqlCmd As New SqlCommand(stQuery, sqlCon)
Dim sqlAda As New SqlDataAdapter(sqlCmd)
sqlCmd.CommandType = CommandType.Text
sqlCmd .Parameters.AddWithValue("#strFirstName", Criteria )
sqlAda.Fill(ds)
End Using
Return ds
Catch ex As Exception
MsgBox(ex.Message.ToString())
End Try
End Function

How do you pull varbinary(MAX) out of SQL Server using DatabaseFactory?

I have a view in SQL Server which gives me varbinary(MAX) data for a PDF copy of a scanned application form (don't ask). Column names in the view include [FileBinary], [Size] and [OriginalFileName].
I use DatabaseFactory throughout the project to pull out data and have not had a problem with types until now. The code to get data from this particular view is:
Public Shared Function GetAppFormPDF(studentRefNo As String) As List(Of ProSolutionReportsAppForm)
Dim db = DatabaseFactory.CreateDatabase(Constants.DataBaseConnectionStringProSolutionReports)
Dim sql As String = String.Format("SELECT * FROM [ProSolutionReports].[dbo].[MC_AppFormSSRS_FromPDFScan] WHERE RefNo LIKE '{0}%'", studentRefNo.Trim())
Return db.ExecuteSqlStringAccessor(Of ProSolutionReportsAppForm)(sql).ToList()
End Function
The model it gets pulled into is declared as:
Public Property FileBinary As System.Data.Linq.Binary
Public Property Size As Long
Public Property OriginalFileName As String
When I hit GetAppFormPDF(), I get told that "The value from column 'FileBinary' cannot be converted to property 'FileBinary' of type 'System.Data.Linq.Binary'."
I created an SQL to Linq DataContext to see how the typing is done there, but (pretty obviously) that's typed to System.Data.Linq.Binary as well and that one works. I also tried typing FileBinary as Byte(), which gives me the data from the rest of the table but sets FileBinary = Nothing.
What do I do to get the varbinary(MAX) data into my model?
After 4 hours of investigation I decided that DataFactory is the wrong way to go about this. Instead I did it the way I should have in the first place:
Dim appForms = New List(Of ProSolutionReportsAppForm)
Dim conn = New SqlConnection(ConfigurationManager.ConnectionStrings(Constants.DataBaseConnectionStringProSolutionReports).ConnectionString)
Dim sql As String = "SELECT * FROM [ProSolutionReports].[dbo].[MC_AppFormSSRS_FromPDFScan] WHERE RefNo = #RefNo"
Dim command As New SqlCommand(sql, conn)
command.Parameters.AddWithValue("#RefNo", studentRefNo.Trim())
conn.Open()
Dim reader As SqlDataReader = command.ExecuteReader()
While reader.Read()
appForms.Add(New ProSolutionReportsAppForm With {.FileBinary = reader("FileBinary"), _
.Size = reader("Size"), _
.ApplicationID = reader("ApplicationID"), _
.RefNo = studentRefNo,
.FirstForename = reader("FirstForename"), _
.Surname = reader("Surname"), _
.OriginalFileName = reader("OriginalFileName")})
End While
reader.Close()
conn.Close()
Return appForms

Checking if database contains table

I created the coding for a program to check if table exists in database. But it keeps underlining restrictions in the coding.
Error 23 Value of type 'String' cannot be converted to '1-dimensional array of String'
Can you please tell me what i did wrong and check if the rest of my coding correct.
Here is the coding:
Dim cn As New SqlClient.SqlConnection(SQL_Loader("", My.Settings.SQL_Win_Auth, _
My.Settings.SQL_Username, My.Settings.SQL_Password, My.Settings.SQL_Server_Name, _
My.Settings.SQL_DB_Name))
Dim Cmd As New SqlClient.SqlCommand
Dim Reader As SqlClient.SqlDataReader
Cmd.Connection = cn
cn.Open()
Dim restrictions As String
restrictions = "Pastel_Companies"
Dim dbTbl As DataTable = cn.GetSchema("Pastel_Companies", restrictions)
If dbTbl.Rows.Count = 0 Then
MessageBox.Show("Table Does Not Exist")
Else
MessageBox.Show("Table exists")
End If
Thank you for any help given
The correct syntax to call GetSchema is the following
Dim restrictions As String() = new String() {Nothing, Nothing, "Pastel_Companies"}
Dim dbTbl As DataTable = cn.GetSchema("TABLES", restrictions)
The first parameter is the collection that you want to check for the existence of the object (in your case you want to check the TABLES collection)
The second parameter contains an array of restrictions. This array changes following the collection that you want to search. For the TABLES collection you should apply three restrictions database, owner and tablename.
The restrictions should appear in the exact order expected, and if you haven't a value to specify you pass a null value (Nothing in VB)
The offers a pretty good clue; you're passing a string as the second argument to GetSchema instead of a one-dimensional array of strings.
Try this:
Dim restrictions() as string = { Nothing, Nothing, "Pastel_Companies" }
Dim dbTbl As DataTable = cn.GetSchema("Tables", restrictions)