SELECTing data from database in vb and outputting data into label - sql

I have the following code which SELECTs data from a database and outputs a value to a label on the form:
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim strConn As String = System.Configuration.ConfigurationManager.ConnectionStrings("yourConnectionString").ToString()
Dim sql As String = "SELECT aid FROM tbl_RAPA WHERE username=#username"
Dim conn As New Data.SqlClient.SqlConnection(strConn)
Dim objDR As Data.SqlClient.SqlDataReader
Dim Cmd As New Data.SqlClient.SqlCommand(sql, conn)
Cmd.Parameters.AddWithValue("#username", User.Identity.Name)
conn.Open()
objDR = Cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection)
While objDR.Read()
Label1.Text = objDR("aid")
End While
End Sub
However, if the value in the database is empty, the program runs into an error. Is there a way for me to do this so the program just returns an empty value rather than crashing?
The error message i am given is System.InvalidCastException: 'Unable to cast object of type 'System.DBNull' to type 'System.Windows.Forms.Label'.' on the line Label1.Text = objDR("aid")

Database objects generally need to be closed and disposed. Using...End Using blocks will do this for you even if there is an error.
Since you are only expecting one piece of data you can use .ExecuteScalar which provides the first column of the first row of the result set. This method returns an object.
Try to always use the the .Add method with Parameters. 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
I had to guess at the database type so, check your database for the real value.
Don't update the User Interface until after the connection is closed and diposed. (End Using). I declared aid before the Using block so, it could be used after the block. Check if the object, aid, is not Nothing before adding it to the label's Text.
Imports MySql.Data.MySqlClient
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim aid As Object
Using conn As New MySqlConnection(ConfigurationManager.ConnectionStrings("yourConnectionString").ToString),
cmd As New MySqlCommand("SELECT aid FROM tbl_RAPA WHERE username=#username", conn)
cmd.Parameters.Add("#username", MySqlDbType.VarChar).Value = User.Identity.Name
aid = cmd.ExecuteScalar
conn.Open()
End Using
If Not IsNothing(aid) Then
Label1.Text = aid.ToString
End If
End Sub

I would add this before While objDR.Read() as a precaution in case your query returns no rows:
if objDR.HasRows
...
Then, to handle the null values (this is probably what you mean by empty):
If Not String.IsNullOrEmpty(objDR.Item("aid")) Then
Label1.Text = objDR("aid")
Else
Label1.Text = "Null !"
End if
You could also use ExecuteScalar() if you are only expecting one record. But you would need to handle the situation where no matching record is found.

Related

Cant update MS Access Database from vb.net

I can add, delete, and search data on my MS access through vb.net application but cant update. It runs and finishes the update query but isn't updating the database, don't get any errors either. I'm new to VB.net and sql and have been following a guide to get what I have so far.
Coding I used for adding new record (Works fine for me):
Private Sub Savebtn_Click(sender As Object, e As EventArgs) Handles Addbtn.Click
Dim Insertquery As String = "Insert into Risk_Register(ID, Risk_Name, Risk_Description, Owner, Control, Probability, Impact, Risk_Level) values (#ID, #Risk_Name, #Risk_Description, #Owner, #Control, #Probability, #Impact, #Risk_Level)"
Runquery(Insertquery)
MsgBox("The record has been added successfully to the database.", 0, "Information")
End If
End Sub
For Update (Not updating)
Private Sub Updatebtn_Click(sender As Object, e As EventArgs) Handles Updatebtn.Click
Dim Updatequery As String = "Update Risk_Register Set Risk_Name=#Risk_Name, Risk_Description=#Risk_Description, Owner=#Owner, Control=#Control, Probability=#Probability, Impact=#Impact, Risk_Level=#Risk_Level Where ID=#ID"
Runquery(Updatequery)
MsgBox("The record has been updated successfully in the database.", 0, "Information")
End Sub
RunQuery Coding
Public Sub Runquery(ByVal query As String)
con = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Users\ahmed\OneDrive\Desktop\ProjectDatabase2003.mdb")
Dim cmd As New OleDbCommand(query, con)
cmd.Parameters.AddWithValue("#ID", txtRiskid.Text)
cmd.Parameters.AddWithValue("#Risk_Name", txtRiskname.Text)
cmd.Parameters.AddWithValue("#Risk_Description", txtRiskdescription.Text)
cmd.Parameters.AddWithValue("#Owner", txtOwner.Text)
cmd.Parameters.AddWithValue("#Control", txtControl.Text)
cmd.Parameters.AddWithValue("#Probability", txtProbability.Text)
cmd.Parameters.AddWithValue("#Impact", txtImpact.Text)
cmd.Parameters.AddWithValue("#Risk_Level", txtRisklevel.Text)
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End Sub
When used with the OleDb provider, Access does not recognize parameters by name. You must supply the parameter values in the order Access expects them.
In your UPDATE, Access expects the #ID value last. But your RunQuery procedure supplies it as the first parameter value.
You can modify the procedure to supply #ID first for an INSERT and last for an UPDATE. Or you can use RunQuery for INSERT and create a separate version for UPDATE.

VB.Net Inserting DateTimePicker to MS Access Database

Good day to everyone here at stackoverflow! I have a simple question that maybe you guys could help me out with. I created a prototype for inserting a DateTimePicker into the MS Access database. I followed this guide:
date time conversion problem when inserting data into sql database and although it helped the person asking the question, it did not help me at all :(
This is the picture and this is my code. This is just a simple prototype that if solved, I will be able to implement it into the actual system I am working on with my classmates.
There is a syntax error apparently. But if I remove just the datetimepicker codes I can insert my last name without any problems and have it show up in MS Access. These are the codes.
Imports System.Data.OleDb
Public Class Form1
Dim conString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Israel De Leon\Documents\dateinsert.accdb;"
Dim con As OleDbConnection = New OleDbConnection(conString)
Dim cmd As OleDbCommand
Dim adapter As OleDbDataAdapter
Dim dt As DataTable = New DataTable()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ListView1.View = View.Details
ListView1.FullRowSelect = True
ListView1.Columns.Add("Last Name", 100)
ListView1.Columns.Add("Date", 100)
End Sub
Public Sub add()
Dim SQL As String = "INSERT INTO Table1(LastName, Time) VALUES (#LastName, #Time)"
cmd = New OleDbCommand(SQL, con)
cmd.Parameters.AddWithValue("#LastName", TextBox1.Text)
cmd.Parameters.AddWithValue("#Time", DateTime.Parse(DateTimePicker1.Value))
'OPEN CONNECTION AND INSERT
Try
con.Open()
If cmd.ExecuteNonQuery() > 0 Then
MsgBox("Succesfully Inserted")
End If
con.Close()
Catch ex As Exception
MsgBox(ex.Message)
con.Close()
End Try
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
add()
End Sub
End Class
Please help this mate out. Thank you :D
The problem is the name of the column Time. Time is a reserved word in MS-Access. You need to put square brackets around that name
Dim SQL As String = "INSERT INTO Table1(LastName, [Time]) VALUES (#LastName, #Time)"
I also strongly suggest you to not use AddWithValue, but the more precise Add where you can properly set the datatype of your parameter and avoid the hidden code of AddWithValue that translates your inputs to the expected ones
cmd.Parameters.Add("#LastName", OleDbType.VarWChar, 100).Value = TextBox1.Text
cmd.Parameters.Add("#Time", OleDbType.DateTime).Value =DateTimePicker1.Value
Notice that the Add method allows you to define also the size of your data in case of text. This allows the database engine to optimize your insert query. (Not sure if this happens also with access but surely with Sql Server this is an important optimization)
Better to use monthCalendar control:
textBox1.Text = monthCalendar1.SelectionRange.Start.Date.ToShortDateString()
cmd.Parameters.AddWithValue("#Time", textBox1.Text)

How do I transfer data from Text Boxes in a form to an Access Table

I'm currently trying to write code for a form that has text boxes for a user to input the required data into which then with the use of button the data in the text boxes will be sent to an access table.
If you need any more information to help solve the problem I'm willing to provide it if you ask (I would upload pictures/screenshots but I need "10 reputation" apparently.
You can do this
Imports System.Data.OleDb
Public Class Form1
Dim AccessConection As OleDbConnection
Private Sub btSave_Click(sender As Object, e As EventArgs) Handles btSave.Click
Dim cmd As New OleDbCommand
Dim mySql As String
mySql = "INSERT INTO Customs (CustomName,Address) VALUES(#Name,#Address)"
Try
cmd.Parameters.AddWithValue("#Name", txName.Text)
cmd.Parameters.AddWithValue("#Address", txAddress.Text)
cmd.Connection = AccessConection
cmd.CommandType = CommandType.Text
cmd.CommandText = mySql
cmd.ExecuteNonQuery()
Catch ex As Exception
MessageBox.Show("Whatever you want to say..." & vbCrLf & ex.Message)
End Try
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim myDataBasePath As String = "C:\Users\user\Source\Workspaces\......\SOF003\Data.accdb" 'Here you put the full name of the database file (including path)
'The next line is for Access 2003 .mdb files
'Dim CadenaConection As String = String.Format("Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}", myDataBasePath)
Dim CadenaConection As String = String.Format("Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0}", myDataBasePath)
AccessConection = New OleDbConnection(CadenaConection)
AccessConection.open()
End Sub
End Class
btSave is the command button.
Customs is the table's name.
CustomName and Address are two fields.
txName and txAddress are two TextBox Control.
Obviously you should be careful with the data types (here I use only strings), validation, etc, etc... But, this is a starting point. If you search, you'll find another ways, more elaborated.

Getting the error "Expression does not produce a value

I am relatively new to using visual basic and I am having a problem populating a list box from a database. The error that comes up is Expression does not produce a value.
Here is the code from My form:
Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Populate Blu Ray and DVD listboxes
Dim objMovies As New clsMovies
objMovies.Select_BR_List()
objMovies.Select_Dvd_List()
For Each strBluRay As String In objMovies.Select_BR_List
lstBluRay.Items.Add(strBluRay)
Next
For Each strDVD As String In objMovies.Select_Dvd_List
lstDvd.Items.Add(strDVD)
Next
End Sub
And here's the code from the class:
Public Sub Select_Dvd_List()
Dim objConnection As New SqlCeConnection(mstrCN)
'Create SQL statement
mstrSQL = "Select * from Dvd"
'Instantiate command
Dim objCommand As New SqlCeCommand(mstrSQL, objConnection)
'open Database
objCommand.Connection.Open()
'Instantiate Data Reader
Dim objDataReader As SqlCeDataReader
'Execute SQL
objDataReader = objCommand.ExecuteReader()
'read Sql results
Do While (objDataReader.Read)
mlstDvd.Add(objDataReader.Item("dvdTitle").ToString)
Loop
'Close
objCommand.Dispose()
objDataReader.Close()
objDataReader.Dispose()
objConnection.Close()
objConnection.Dispose()
End Sub
The issue is that you're trying to enumerate a Sub. In VB.NET, methods can either a Sub, which doesn't return a value, or a Function, which does return a value. Your Select_Dvd_List method is a Sub, so it doesn't return a value. You have this code though:
For Each strDVD As String In objMovies.Select_Dvd_List
That is trying to loop through the result of Select_Dvd_List but, as we've already established, Select_Dvd_List has no result. In that method, you are adding items to mlstDvd so surely that loop should be:
For Each strDVD As String In objMovies.mlstDvd

already an open DataReader associated with this Command when am chekcing with invalid data

Private Sub txt_sname_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles txt_sname.GotFocus
Dim fcs As String
fcs = "select fname,dept from nstudent where stid = '" & txt_sid.Text & "'"
scmd1 = New SqlCommand(fcs, con)
dr1 = scmd1.ExecuteReader
If dr1.HasRows Then
Do While (dr1.Read)
txt_sname.Text = dr1.Item(0)
cmb_dept.Text = dr1.Item(1)
Loop
Else
MsgBox("Not Found")
End If
scmd1.Dispose()
If Not dr1.IsClosed Then dr1.Close()
End Sub
The above code for data from database and pass to textbox. When am running the program and checking with data which already present in database, it working properly. but checking with some other data(which not present in db)following error is occurring and exiting.
error:
"There is already an open DataReader associated with this Command which must be closed first."
pls help me..
Some observations:
Instead of using a global command object, use a local one. Especially since you are creating a new command anyway. And it looks like this is true of the dr1 as well.
You are not preventing SQL injection, so someone can type text in txt_sid that causes security issues by deleting data, dropping tables, or getting access to other data in the database.
You are looping and setting the same variables multiple times. If there is only going to be one record, don't bother looping.
Wrap the entire thing around a try/catch
Private Sub txt_sname_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles txt_sname.GotFocus
Dim cmd1 As SqlCommand = New SqlCommand(fcs, "select fname,dept from nstudent where stid = #stid")
cmd1.Parameters.Parameters.AddWithValue("#stid", txt_sid.Text)
Dim studentReader as SqlDataReader
Try
studentReader = scmd1.ExecuteReader
If studentReader.Read Then
txt_sname.Text = studentReader.Item(0)
cmb_dept.Text = studentReader.Item(1)
Else
MsgBox("Not Found")
End If
Finally
studentReader.Close()
cmd1.Dispose()
End Try
End Sub
Finally, I think you might want to actually do this when txt_sid changes, not when txt_sname gets focus.