How to read date and time from database and compare it to the system date and time - vb.net

I am working on a project using vb and one of my forms has to display the current active reminders (reminders that haven't hit their deadline yet) into a datagridview and I have another datagridview for reminders that are past the deadline. The date and time along with reminder information is saved into my access database and I want to read the date and time from database and compare it to the system date and time and then display the reminder information.
This is how my form looks like; the top datagridview is for current reminders and the bottom one is for past/out of date reminders:
This the code for my form and what I’ve tried:
Imports System.Data.OleDb
Public Class frmReminderInfo
Private Sub frmReminderInfo_Load(sender As Object, e As EventArgs) Handles MyBase.Load
DisplayCurrentReminders()
End Sub
Private Sub DisplayCurrentReminders()
Dim ReminderDateTime As Date
Dim CurrentDateTime As Date
CurrentDateTime = Date.Now
CurrentDateTime = FormatDateTime(Date.Now, DateFormat.GeneralDate)
ReminderDateTime = FormatDateTime(ReminderDateTime, DateFormat.GeneralDate)
If DbConnect() Then
DgvCurrentReminders.Rows.Clear()
Dim SQLCmd As New OleDbCommand
With SQLCmd
.Connection = cn
.CommandText = "SELECT ReminderDate FROM TblReminder "
Dim rs As OleDbDataReader = .ExecuteReader()
While rs.Read
ReminderDateTime = (rs(0).ToString)
End While
End With
End If
cn.Close()
If CurrentDateTime = ReminderDateTime Then
Dim SQLCmd As New OleDbCommand
With SQLCmd
Dim rs As OleDbDataReader = .ExecuteReader()
While rs.Read
Dim NewStockRow As New DataGridViewRow()
NewStockRow.CreateCells(DgvCurrentReminders)
NewStockRow.SetValues({rs("ReminderID"), rs("CustomerName"), rs("DeviceInfo"), rs("RepairPrice"), rs("ReminderDate")})
NewStockRow.Tag = rs("ReminderID")
DgvCurrentReminders.Rows.Add(NewStockRow)
End While
rs.Close()
End With
End If
cn.Close()
End Sub
End Class

Disposable database objects like Connection should be declared locally in the method where they are used in a Using block.
You don't seem to have any idea of what the parts of an Sql string mean. The Select portion list the fields you want to retrieve. A star (*) in this clause means select all the fields. Here we are using a Where clause to filter the records. Only records where the field ReminderDate is greater than or equal to a parameter will be returned. This will only work if the data has been inserted properly as a DateTime.
The While loop keeps overwriting the value of ReminderDateTime on each iteration so only the last value returned by the reader will remain. Also, you are trying to force a String into a variable declared as a Date. Won't work.
Assuming the code could get beyond If CurrentDateTime = ReminderDateTime Then you would be working with a closed connection. Commands can't execute on a closed connection.
You also don't seem to have an idea how class objects work. Dim SQLCmd As New OleDbCommand Here you declare a new instance of the Command. You have no connection and no CommandText so it can't possibly be executed.
Take a look at the following code until it starts to make sense. Look up what Using blocks do. Look up the Load method of a DataTable to see what it does. Check out what a DataSource property has to offer.
Private Sub frmReminderInfo_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = GetCurrentReminders()
DgvCurrentReminders.DataSource = dt
End Sub
Private Function GetCurrentReminders() As DataTable
Dim dt As New DataTable
Using cn As New OleDbConnection("Your connection string"),
SQLCmd As New OleDbCommand("SELECT * FROM TblReminder Where ReminderDate >= #Date", cn)
SQLCmd.Parameters.Add("#Date", OleDbType.Date).Value = Now
cn.Open()
Using reader = SQLCmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function

Related

In VB.Net, how to repopulate a datagrid from scratch?

I have written a generic VB.net subroutine that populates a datagrid with the results of a query. The subroutine as one parameter, strQuery, which is a string that can translate to any valid SQL-Server view or stored procedure that returns a recordset. Other than that, there is no constraint on the SQL code, and sending two queries that have entirely different field profiles is a valid proposition.
In order to get this to work, I must completely purge the data grid of whatever dataset had been there previously, thus allowing the control to drop its prior identity and start over, allowing, from scratch, the new dateset to redefine the control's contents.
I have finally solved the problem. Perhaps I should have mentioned that I am using Visual Studio 2010, and that if Hersey were using a later version, then the code that worked for him may not have worked for me. The change to my code is one additional line: setting both the name and datapropertyname to the same name. I noticed that when I went to look at the column view, I noticed that the datapropertyname is how the table links to the source, and the name is an effective alias for the field, how it will be presented. Obviously, for clarity sake, both must be the same! This now works as advertised.
Thanks, ~ Peter Ferber
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim con As New SqlConnection("<Enter Connection string here>")
Dim rcd As ADODB.Recordset = ReturnRecordset("Select * From ExcludeWords")
Call DefineDataGrid("Select * From ExcludeWords")
End Sub
Private Sub btnUpdate_Click(sender As System.Object, e As System.EventArgs) Handles btnUpdate.Click
Call DefineDataGrid("Select * From FindWords")
End Sub
Sub DefineDataGrid(ByVal strQuery As String)
Dim con As New SqlConnection("<Enter Connection String Here>")
Dim dt As New DataTable
FindWordGrid.Columns.Clear()
FindWordGrid.DataSource = Nothing
Dim rcd As ADODB.Recordset = ReturnRecordset(strQuery)
Dim MyField As ADODB.Field
Dim iCount As Integer = -1
FindWordGrid.ColumnCount = rcd.Fields.Count
For Each MyField In rcd.Fields
iCount = iCount + 1
FindWordGrid.Columns(iCount).Name = MyField.Name
FindWordGrid.Columns(iCount).DataPropertyName = MyField.Name
Next
Dim cmd As New SqlCommand(strQuery, con)
Dim da = New SqlDataAdapter(cmd)
da.Fill(dt)
FindWordGrid.DataSource = dt
End Sub
Function ReturnRecordset(strQuery As String) As ADODB.Recordset
Dim con As ADODB.Connection = "<Enter Connection string here>"
ReturnRecordset = New ADODB.Recordset
ReturnRecordset.Open(strQuery, con)
End Function
My setup is easy to reproduce: I am using datasets with only a handful of records in each respective table. The only constraint is that the respective runs must have a different field profile. I have been experimenting with different techniques for much of the day, and I now think it best to get some new grey matter on the subject. Getting this process correctly is the last major hurdle for me, in making a key presentation I wish to make, in lobbying for a job role. Thanks, in advance, for your comments, thoughts, and ideas.
Sincerely, ~ Peter Ferber
So, made a couple modifications to the DefineDataGrid code you've posted. Seems to be working for me. I suspect might be something to do with the life cycle of either your cmd or con objects causing your problem. Parsing a number of different number of queries through to it and it rebuilds the datagridview correctly
Sub DefineDataGrid(ByVal strQuery As String)
Dim dt As New DataTable
FindWordGrid.DataSource = Nothing
Using con As New SqlConnection("Your Connection String Here")
Using cmd As New SqlCommand(strQuery, con)
Dim da = New SqlDataAdapter(cmd)
da.Fill(dt)
FindWordGrid.DataSource = dt
End Using
End Using
End Sub
Changed the obvious module level implementations of con and cmd to local variables, and since both types implement IDisposable, wrapped them in a Using pattern

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

Trying to delete a record from my access database in visual basic studio 2010

Private Function CreatePlayerAdapter(ByVal playerDBconnection As OleDbConnection) As OleDbDataAdapter
// Initiating instances for the function
Dim dataAdapter As OleDbDataAdapter = New OleDbDataAdapter()
Dim myCommand As OleDbCommand
Dim parameter As OleDbParameter
// establishing the string to tell where to delete record from and how to find the record i want.
// PlayerIDTextBox.Text is a text on a form that is populated from the database after selecting a list of name (this works correctly) // connection is already open and is directed to correct place
Dim sql As String = "DELETE * FROM Players WHERE ID ='" & CInt(PlayerIDTextBox.Text) & "'"
myCommand = New OleDbCommand(sql, playerDBconnection)
parameter = myCommand.Parameters.Add("ID", OleDbType.Char, 3, "ID")
parameter.SourceVersion = DataRowVersion.Original
dataAdapter.DeleteCommand = myCommand
Return dataAdapter
End Function
// i call this function after executing a button click.
//ListPlayerComboBox.Text is populated with the names and needs it a name to fill PlayerIDTextBox.Text(works correctly)
Private Sub RemovePlayerButton_Click(sender As System.Object, e As System.EventArgs) Handles RemovePlayerButton.Click
If ListPlayerComboBox.Text = " " Then
MsgBox("Please Select a Player.")
Else
Me.CreatePlayerAdapter(playerDBConnection)
End If
End Sub
// no errors occur. However, nothing is done in the database. help please?
Notes:
1)Never leave your OleDbConnection Open. Only allow it to be opened when you actually need it. This will save you from a lot of headaches later on. The reasons why can be found on following stackoverflow question.
2) There is no reason to return an OleDbDataAdapter if you don't intend on using it.
3) Use your parameters correctly : see below example2
4) Keep in mind that there are some restricted keywords in Access. Luckely for you ID isn't one. The restrictedKeywords can be found here: Keywords
I'm probably missing some further points here. Anyone should be free to add em.
Why not adjust your Function CreatePlayerAdapter to the following:
1) Without parameters
Private Sub CreatePlayerAdapter(ByVal playerDBconnection As OleDbConnection)
Dim myCommand As OleDbCommand
Dim sql As String = "DELETE * FROM Players WHERE ID =" & CInt(PlayerIDTextBox.Text)
myCommand = New OleDbCommand(sql, playerDBconnection)
playerDBconnection.Open()
myCommand.ExecuteNonQuery()
playerDBconnection.Close()
End Sub
2) With parameters
Private Sub CreatePlayerAdapter(ByVal playerDBconnection As OleDbConnection)
Dim myCommand As OleDbCommand
Dim sql As String = "DELETE * FROM Players WHERE ID = #playerId"
myCommand = New OleDbCommand(sql, playerDBconnection)
Dim param As New OleDb.OleDbParameter(#playerId", CInt(PlayerIDTextBox.Text))
myCommand.Add(param)
playerDBconnection.Open()
myCommand.ExecuteNonQuery()
playerDBconnection.Close()
End Sub
The method ExecuteNonQuery executes the query passed to the command on the specified OleDbConnection and returns the number of rows affected. More info Here

how to populate items from database in a listbox in vb.net

I was developing an application using oop concept.I have a class that has 2 attributes and have Get and Set methods namely WorkItemNumber and Description.
On the client side i have a list box used to populate the work items based on their description.Here's the code i wrote in the class o read items from the database.
Public Sub LoadWorkItem()
' Load the data.
' Select records.
Dim oWorkItem As WorkItem = New WorkItem()
Dim conn As New OleDbConnection
Dim data_reader As OleDbDataReader
conn = oWorkItem.GetDbConnection()
Dim cmd As New OleDbCommand("SELECT * FROM work_item ORDER BY [work item number]", conn)
data_reader = cmd.ExecuteReader()
'ListBox1.Items.Clear()
If data_reader.HasRows = True Then
Do While data_reader.Read()
WorkItemNumber = data_reader.Item("work item number")
Description = data_reader.Item("description")
Loop
End If
data_reader.Close()
data_reader = Nothing
cmd.Dispose()
cmd = Nothing
conn.Close()
conn.Dispose()
End Sub
How do i populate the listbox using the code,and if there's any improvement on the code please do tell me as well.Thank you
To poulate your ListBox, do this...
ListBox1.Item.Clear()
If data_reader.HasRows Then
Do While data_reader.Read()
WorkItemNumber = data_reader.Item("work item number")
Description = data_reader.Item("description")
ListBox1.Items.Add(New ListItem(Description, WorkItemNumber)
Loop
End If
As far as improvements, start by using a Using statement for the DB connection. In your code, if there is an exception while the database connection is open, it will never get closed. This is better...
Using conn As OleDbConnection = oWorkItem.GetDbConnection()
' Execute SQL and populate list...
End Using
The above code assures that your connection will be closed.
Then, turn on Option Strict and Option Explicit. This will force you to declare the Type for Description and WorkItemNumber and cast them as Strings when adding a ListItem. This will reduce run-time errors.
Finally, if this is anything but a small app you are doing as a learning experiment, you should read up on tiered application design. Your code is mixing UI, business logic, and data access in the same method. This is generally frowned upon.
Your "user interface" LoadWorkItem() method should ask a "core" method for a list of WorkItems.
Your core method should then ask a "data access" method for data.
The "data access" method should make the call to the database.
Happy coding.
Update: You can find excellent info about n-Tier architecture on MSDN. A good book to read once you grasp the fundamentals and have some confidence in .NET is Visual Basic .NET Business Objects.
Imports System.Data.SqlClient 'Reference The Sql Client
Public Class Form1
''Make sure to change the connection string below to your connection string this code only works for SQL DataBase. If Your connection String is wrong This will Not Work
Dim connString As String = "Data
Source=NameofYourSQLServer\SQLEXPRESS;Initial Catalog=NameOfYourDataBase;Integrated Security=True"
Dim tblDIV As DataTable
Dim daDIV As SqlDataAdapter
Dim dsDIV As New DataSet
Dim oCon As SqlConnection
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim oCon = New SqlConnection
oCon.ConnectionString = connString
dsDIV = New DataSet
' Select all Fields and order by ID or Replace * with name of Field
daDIV = New SqlDataAdapter("SELECT * FROM NameOfYourTable ORDER BY Id DESC", oCon)
'*** Define command builder to generate the necessary SQL
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(daDIV)
builder.QuotePrefix = "["
builder.QuoteSuffix = "]"
Try
daDIV.FillSchema(dsDIV, SchemaType.Source, "DIV")
daDIV.Fill(dsDIV, "DIV")
tblDIV = dsDIV.Tables("DIV")
ListBox1.DataSource = tblDIV
ListBox1.DisplayMember = "NameOfTheFieldYouWanttoDisplay"
Catch ex As Exception
MsgBox("Encountered an Error;" & vbNewLine & ex.Message)
oCon.Close()
End Try
End Sub

Fill DataGridView with data from SQL

I want to fill a DataGridView with data returned from a SQL. So here is my code [I provided cause some people may think I'm asking for help before trying myself]
I want the DataGridView to be filled by a data from SQL not to show all the records.
The SQL "Select * From books where title='php%' Order By Title;"
useless code :( :'( :<
Imports System.Data
Imports System.Data.SqlClient
Public Class frmMain
Dim connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\Database.mdb;Persist" & " Security Info=True"
Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.BooksTableAdapter.Fill(Me.TblBooks.books)
End Sub
Private Sub txtTerm_TextChanged() Handles txtTerm.TextChanged
If Trim(txtTerm.Text) = "" Then Exit Sub
Dim tblCustomBooks As New DataTable
Dim adpBooks As New OleDb.OleDbDataAdapter("Select * From books where title='php%' Order By Title", _
'"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\Database.mdb;Persist" & " Security Info=True")
adpBooks.Fill(tblCustomBooks)
BooksTableAdapter.Fill(tblCustomBooks)
'Dim myConnection As SqlConnection
'Dim myCommand As SqlDataAdapter
'myConnection = New SqlConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\Database.mdb;Persist" & " Security Info=True")
'myCommand = New SqlDataAdapter("Select * From books where title='php%' Order By Title", myConnection)
'Dim ds As DataSet = New DataSet()
'myCommand.Fill(ds)
'gridTable.DataSource = ds
End Sub
Looks like you've tried a number of different things, but it's not apparent from your code what order you tried them in. Based on the current version of your code, you're missing two things:
First, an OleDBConnection object to use with the OleDbDataAdapter.
Second, you're not assigning anything to the DataGridViews DataSource property, so nothing will show up.
Also, you appear to be using two different OleDbDataAdapters (or maybe two different DataAdapters altogether) to fill tblCustomBooks, so depending on what BooksTableAdapter is set up as may also be causing you problems.
Try this:
Private Sub txtTerm_TextChanged() Handles txtTerm.Changed
If Trim(txtTerm.Text) = "" Then Exit Sub
Dim tblCustomBooks As New DataTable
Using conn As New OleDbConnection(connectionString)
Dim adpBooks As New OleDbDataAdapter("SELECT * FROM books WHERE title = 'php%' ORDER BY title", conn)
adpBooks.Fill(tblCustomBooks)
gridTable.DataSource = tblCustomBooks
End Using
End Sub
See:
DataGridView.DataSource Property
OleDbDataAdapter Class
In your SQL statement try [WHERE Title LIKE 'php%'] instead of [WHERE Title = 'php%'].
I've run into similar problems with MS SQL and this was the fix. I'm not sure if the SQL syntax is the same for the Jet provider, but it's worth a try at least.
HTH
dim dt as new datatable
'i already maked the class and now load from a database
dt=cls.getdata("select * from tblinf")
datagridview1.datasource=dt