InvalidCastException in Linq to entities query - vb.net

I am making an application for my department at work. I have run into a big problem.
I am trying to get the primary key of a name selected on a ListBox control. This ListBox control is populated from a query from the database when the form loads. Below is the query used to populate the ListBox control.
Dim examinationOfficer As New ExamOfficerPayEntities
Dim findOfficer = From officer In examinationOfficer.Exams_Officer
Order By officer.First_Name Ascending
Select officer.First_Name.ToUpper & " " & officer.Last_Name.ToUpper
lstFullname.DataSource = findOfficer.ToList
lstFullname.DisplayMember = "FullName"
The query works fine and the ListBox is populated as expected. The problem is I am trying to get the value of the primary key of the selected ListBox item. The primary key value I am trying to retrieve is an integer value and it is set as an identity.
Below is a summary of my database.
Table Exam_Officer:
Officer_ID as int which is the primary key and is also set as an identity column
First_Name as nvarchar
last_Name as nvarchar
One other Table is Result_Submitted,
its columns are:
sn as integer primary key and an identity column
Officer_ID as an int and is a foreign key to the Table Exam_Officer
Result_Submitted as nvarchar
Outstanding_Result as nvarchar
This is the code I am trying to use to get the officer_ID from the SelectedItem property of the ListBox control of a Windows form.
Dim selectedOfficer As Exams_Officer = DirectCast(lstFullname.SelectedItem, Exams_Officer)
Dim selectedOfficerID As Integer = selectedOfficer.Officer_ID
The code dosen't work it throws an error on the first line (directcast method)
System.InvalidCastException was unhandled
Message=Unable to cast object of type 'System.String' to type 'EXAMINATION_OFFICER_PAYMENT.Exams_Officer'.
Source=EXAMINATION OFFICER PAYMENT
I am confused and don't know what else to do. Any help is appreciated.

To be honest, I'm surprised it's even displaying at the moment as FullName isn't a property of String. Look at your code:
Dim examinationOfficer As New ExamOfficerPayEntities
Dim findOfficer = From officer In examinationOfficer.Exams_Officer
Order By officer.First_Name Ascending
Select officer.First_Name.ToUpper & " " & officer.Last_Name.ToUpper
You're selecting the full name - so the result of your code is just the names, not the original officers. I suspect you want:
Dim examinationOfficer As New ExamOfficerPayEntities
Dim findOfficer = From officer In examinationOfficer.Exams_Officer
Order By officer.First_Name Ascending
lstFullname.DataSource = findOfficer.ToList
lstFullname.DisplayMember = "FullName"
At that point, you've got a list of officers rather than a list of strings. This is assuming FullName is a property of your officer type though. If it's not, you might want to project to a list where you do the string concatenation in one property, but keep the original officer in another property. For example:
Dim examinationOfficer As New ExamOfficerPayEntities
Dim findOfficer = From officer In examinationOfficer.Exams_Officer
Order By officer.First_Name Ascending
Select New With {
.FullName = officer.First_Name.ToUpper & " " _ & officer.Last_Name.ToUpper,
.Officer = officer
}
lstFullname.DataSource = findOfficer.ToList
lstFullname.DisplayMember = "FullName"
Then later, you'd need to extract the value of the Officer property to get at the officer object itself.

In general the way to do this is to add Officers to your ListBox and override Officer's ToString() method to return FullName, or bind and set DisplayMember to Fullname. Like Jon Skeet, I'm not sure why the code you've posted is working...
Then you can do
Dim selectedOfficer As Exams_Officer = DirectCast(lstFullname.SelectedItem, Exams_Officer)
and Exams_Officer.OfficeID will be okay.
At the moment you are casting a string to an Officer, the above casts an Object to an Officer, which is more likely to work.
Bear in mind however that you need to instance all your officers and that they'll be in memory. So if had a lot of and/or Officer was a hefty object, performance might start to suffer.
The simplest option at that point is a small class / structure with just ID and name in it.

Related

Find data location based on Primarykey ID

I am very new to access and vba so apologies in advance for glaring conceptual gaps.
Basically I have a button that, when clicked, prompts a user to enter an ID number. The ID entered will correspond to one of my primary keys in a specific table (I have some checks in place to make sure the entered ID is valid).
I need my code to identify the row number of the ID entered and be able to populate a specific column in that row. I know Access does not refer to data locations using rows/cols but that is the best way I thought to describe it.
I am using Index/Seek/NoMatch to make sure the entered ID number is valid and I have been trying to find a way to also use those functions to generate the data location but have not had any luck. Any help would be greatly appreciated.
I think DLookup() function will work for your case. Suppose you have following dataset in table tblEmpInfo where EmpID is primary key field.
If you want to return employee name by entering employee id in a inputbox then use DLookup() like below-
Private Sub cmdDataLookup_Click()
Dim strEmpName As String, InputID As String
InputID = InputBox("Enter employee ID:", "Input ID")
strEmpName = DLookup("EmpName", "tblEmpInfo", "EmpID= '" & InputID & "'")
MsgBox strEmpName
End Sub
If you want to update any name by entering EmpID then use UPDATE SQL statement. Try below.
Private Sub cmdUpdateInfo_Click()
Dim strSQL As String, InputID As String
InputID = InputBox("Enter employee ID:", "Input ID")
strSQL = "UPDATE tblEmpInfo Set EmpName= 'Updated Value' WHERE EmpID= '" & InputID & "'"
CurrentDb.Execute strSQL
End Sub
Note: There is no direct way to get row number and column number of a Field in access but you can apply some trick by VBA to get row and column number of a Field. I will suggest to ask a separate question to get that.

SQL Injection from a textbox

I'm new to MS Access.
So, I wrote a SQL query(query name = qryEmployeeInfo) which shows employee information. The query outputs two columns. The employee ID(header name = employee_ID) and the corresponding employee address(header name = employee_address).
My Access form has a text box(text box name = txtEmployeeID) that I want the user to be able to enter the employee_ID into and have it output the corresponding employee_address into another text box (text box name = txtEmployeeAddress). I also want the employee_address to be in the format of a string variable so I can perform other VBA checks on it later(for example - if LIKE "California" THEN...something).
I want to write what (I think) is called an injection SQL query so that I can pull the address data from the query for that specific employee_ID. I believe the format should look like this:
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("select employee_address from qryEmployeeInfo where employee_ID = "' & txtEmployeeID & "'", dbOpenDynaset)
Do I have this written correctly?
If so, then how do I get that output into a string variable format(variable name = strEmployeeAddress)?
After I get the employee address into a string variable format I want to simply use txtEmployeeAddress.value = strEmployeeAddress to populate the employee address text box. Again, I also want the employee_address to be in the format of a string variable so I can perform other VBA checks on it later(for example - if LIKE "California" THEN...something).
Any help you could provide would be greatly appreciated.
If employee_ID is a number field, remove apostrophe delimiters.
If employee_ID is a text field, move first apostrophe so it is within quote marks.
"select employee_address from qryEmployeeInfo where employee_ID = '" & txtEmployeeID & "'"
Then txtEmployeeAddress = rs!employee_address
However, instead of opening a recordset object, could just use DLookup.
txtEmployeeAddress = DLookup("employee_address", "qryEmployeeInfo", "employee_ID =" & txtEmployeeID)
Or even better, eliminate the VBA. The DLookup() expression can be in textbox ControlSource property, just precede with = sign.
However, domain aggregate functions can perform slowly. So instead of textbox, use a combobox for selecting employee. Include employee information in combobox RowSource. Expression in textbox references column of combobox: =combobox.Column(1). Issue is combobox has limit on how many characters can be pulled into column so if field is memo (long text) type, this approach is not feasible and should use DLookup.
The address will be available in textbox for use as long as this form is open. If you want the address to be available to other procedures even after form is closed, then need to set a global or public variable. Such variable must be declared in a module header to make it available to multiple procedures. TempVars are another way to hold values for future use. I have never used them.

Inserting Records into a database

Whenever i run the code and try to run the SQL query it says Datatype mismatch
The code is as follows:
Public Class Form7
Public insert As New DBController
Public username, password, ID As String
Public chars(20) As Char
Public cc As Integer
Private Sub BTNSaveRecord_Click(sender As Object, e As EventArgs) Handles BTNSaveRecord.Click
chars = TXTLastName.Text.ToCharArray
ID = chars(0) & chars(1) & chars(2)
insert.AddParameters("#ID", ID)
insert.MakeQuery("SELECT Driver_ID FROM Driver WHERE Driver_ID LIKE '%#ID%'")
ID = ID & (insert.recordcount + 120).ToString
insert.clearDT()
cc = Conversion.Val(TXTCarCapacity.Text)
MsgBox(cc)
insert.AddParameters("#ID", ID)
insert.AddParameters("#Fname", TXTFirstName.Text)
insert.AddParameters("#Lname", TXTLastName.Text)
insert.AddParameters("#CarCap", cc)
insert.AddParameters("#pass", "Password1")
username = TXTFirstName.Text & TXTLastName.Text.First
MsgBox(username)
MsgBox(ID)
insert.AddParameters("#user", username)
insert.MakeQuery("INSERT INTO Driver (Driver_ID,Maximum_Case_Capacity,Driver_Username,Driver_Password,Driver_FirstName,Driver_LastName) " &
"VALUES (#ID,#CarCap,#user,#pass,#Fname,#Lname);")
End Sub
If you want to know the code for the DB controller i have the code. That is a self defined class to make the SQL stuff less repetitive. Like the data adapters command builders and datatables.
This is the table in the database I am inserting a new record in. This has no relationships too it that will stop me from entering a new record. The image contains the datatype types of each field
Details for maximum_case_capacity
Access does not care what you call your parameters; the names are ignored. It is the order the parameters are added that matches them to the database. Since the order of the fields do not match the order the parameters are added you are getting a type mismatch when Access tries to add the string FName to the numeric field Maximum_Case_Capacity.
insert.AddParameters("#ID", ID)
insert.AddParameters("#CarCap", cc)
username = TXTFirstName.Text & TXTLastName.Text.First
insert.AddParameters("#user", username)
insert.AddParameters("#pass", "Password1")
insert.AddParameters("#Fname", TXTFirstName.Text)
insert.AddParameters("#Lname", TXTLastName.Text)
In a real application, you would never add passwords as plain text. Also, the interesting dance you do to get a unique primary key (maybe) could be avoided if you used a numeric autoincrement field in Access. I am afraid you will run out of space in that field rather quickly as it is only 6 characters wide. Hope you don't get too many people named Smith. ;-)

How do i obtain foreign table field using string value for fieldname with reflection and entity framework

I have 2 tables. An asset table that links using a foreign key to a device table.
To get the device_name field of the asset, in linq i would use:
dim device as string = result.device.device_name
The Result object contains the unique record from an earlier linq to entity framework command.
Now I have a need to allow end users to specify their fields they want in a report. I will end up having a string name of the field, so tried using reflection
dim name as string = result.GetType().GetProperty("asset_name").GetValue(result)
This returns the asset_name field so i thought great, i should be able to get the relating foreign table field value.
dim device = result.GetType().GetProperty("device").GetValue(result).GetType.GetProperty("device_name").GetValue(result.device)
This works however i had to specify the object. As i will have other tables linking to the first table, would i have to write additional code to check what object and manually specify? Or am i going into this wrongly? Any help and advice appreciated.
I couldn't find a cleaner solution, so this is how i did it:
dim field as string ="device.device_name"
dim output as string =""
dim subtable as string =""
If field.Contains(".") Then
subtable = field.Substring(0, field.IndexOf("."))
field = field.Substring(field.IndexOf(".") + 1)
End If
If subtable <> "" Then
Select case subtable
Case "device"
If Not IsNothing(result.device.GetType().GetProperty(field)) Then
output = result.device.GetType().GetProperty(field).GetValue(result.device)
End If
End Select
Else
If Not IsNothing(result.GetType().GetProperty(field)) Then
output= result.GetType().GetProperty(field).GetValue(reult)
End If
End If
Return output

Connection with MS Access 2010 via vb.net

Dim newRow As DataRow = dt.NewRow
newRow.Item(1) = Student_IDTextBox.Text
newRow.Item(2) = Student_NameTextBox.Text
newRow.Item(3) = Date_of_BirthDateTimePicker.Text
newRow.Item(4) = AddressTextBox.Text
newRow.Item(5) = E_mailTextBox.Text
newRow.Item(6) = AllergiesTextBox.Text
newRow.Item(7) = Emergency_Contact_NumberTextBox.Text
dt.Rows.Add(newRow)
The line
newRow.Item(2) = Student_NameTextBox.Text
gives a error saying:
"String was not recognized as a valid DateTime. Couldn't store <> in Date of Birth Column. Expected type is DateTime."
But I checked the database the second row is the Student name Field.
I think the code is starting to input the student name into the student ID field in the database, The Student Id is the primary key coe this be why it isn't storing the student_IDtextbox data in its specified field?
I realy need help with this my project is due in about 9 days!
the columns index in DataRow class, Similar all indexs in vb.net, its zero-based.
first column is zero, second one and ect.