retrieving null date from database to vb.net - mysql

i am having a problem in recovering a null date from my database into datepicker in vb.net.
i was able to save a datein mysql with a null value but can't retrieve it to datepicker.
i tried this code but it doesn't work.
If reader.IsDBNull(0) Then
Return
Else
refdate.Text = reader.GetString("refdate")
End If
my code for retrieving is
Try
If e.RowIndex >= 0 Then
Dim row As DataGridViewRow
row = Me.DataGridView1.Rows(e.RowIndex)
forid.Text = row.Cells("id").Value.ToString
Try
connection.Open()
Dim sel As String
sel = "select * from recordtracker where id ='" & forid.Text & "'"
com = New MySqlCommand(sel, connection)
reader = com.ExecuteReader
While reader.Read
Cancel.Show()
Clear.Hide()
rdate.Enabled = False
rfromtbx.Enabled = False
doctype.DropDownStyle = ComboBoxStyle.DropDown
ID.Text = reader.GetInt32("id")
doctype.Text = reader.GetString("Type_of_Document")
itemtbx.Text = reader.GetString("Items")
rfromtbx.Text = reader.GetString("Received_From")
rdate.Text = reader.GetString("Received_Date")
remarks.Text = reader.GetString("Remarks")
margnote.Text = reader.GetString("Marginal_Note")
reftotbx.Text = reader.GetString("Referred_To")
acttaken.Text = reader.GetString("Action_Taken")
'refdate.Text = reader.GetString("refdate")
'If reader.Read() Then
If reader.IsDBNull(0) Then
Return
Else
refdate.Text = reader.GetString("refdate")
End If
Delete.Show()
' End If
End While
Catch ex As Exception
MsgBox(ex.Message)
End Try
any help is appreciated.

For future use, this was the answer needed by the asker.
reader.IsDBNull(0) gets the value of index zero which I presume that refdate is not in the first index.
Using reader.GetString("refdate") gets the String value; therefore, when retrieving null value, it returns error so better use isDbNull(reader("refdate")) to check if the field is null or not. To get the String value, you can simply use reader("refdate").toString

Related

How to check only month and year in MySQL DateTime column in Vb.net

Im saving some calculated values in to database each month.Before saving, i want to check data is already available for this month and year. IF the same month exists, then user has to select another month or leaving without saving that. In Vb.net, im using DateTimepicker for selecting month and save that in DateTIme format in mysql. In that i want to check only month and year is existing.
Mysql:
1 2019-05-01 14:24:20 ProA 8.34 3.59
2 2019-05-01 14:24:20 ProB 9.21 5.54
Here record available for ProA for May2019 is available. So user cannot save for may 2019 again.
Dim selectedDate = DateTimePicker1.Value
Dim startDate = New Date(selectedDate.Year, selectedDate.Month, 1)
conn.Open()
sQuery = "SELECT * FROM riskanalysis WHERE DATE_FORMAT(reportdate,'%c %Y') >= #StartDate "
cmd_listview = New MySqlCommand(sQuery, conn)
cmd_listview.Parameters.AddWithValue("#StartDate", startDate)
Using reader As MySqlDataReader = cmd_listview.ExecuteReader()
If reader.HasRows Then
' User already exists
MsgBox("Record Already Exist for this Month!", MsgBoxStyle.Exclamation, "Select another month!")
Else
sQuery = "INSERT INTO riskanalysis (reportdate, process, avgrisk, avgriskafterImp) VALUES (#dat, #process, #avgrisk, #riskafterimp);"
For i As Integer = 0 To ProcessRiskGridView.Rows.Count - 1
cmd_listview = New MySqlCommand(sQuery, conn)
cmd_listview.Parameters.AddWithValue("dat", DateTimePicker1.Value)
cmd_listview.Parameters.AddWithValue("process", ProcessRiskGridView.Rows(i).Cells(0).Value)
cmd_listview.Parameters.AddWithValue("avgrisk", ProcessRiskGridView.Rows(i).Cells(1).Value)
cmd_listview.Parameters.AddWithValue("riskafterimp", ProcessRiskGridView.Rows(i).Cells(2).Value)
cmd_listview.ExecuteNonQuery()
Next
End Using
conn.Close()
I tried for some mysql command but it didnt work.
You don't need to Select * to find out if a record exists. Just get the count. Don't retrieve data you don't need. You certainly don't need a reader.
Keep your database objects local so you can be sure they are closed and disposed. `Using...End Using blocks will handle this for you even if there is an error.
Don't use .AddWithValue 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
You keep adding parameters to the collection over and over on each iteration. They only need to be added once. The value of #dat remains the same for all iterations. Only the values of the last 3 parameters change. You seem to be mixing up column names and parameter names. We are dealing with parameter names.
I have guessed at datatypes. Check your database for the actual datatypes and be sure to convert the values from the grid cells to the proper type if necessary. I don't know what kind of grid you are using and if it returns proper datatypes for .Value.
Example:
cmd.Parameters("#avgrisk") = CDbl(ProcessRiskGridView.Rows(i).Cells(1).Value)
Private Sub MySql()
Dim retVal As Integer
Dim selectedDate = DateTimePicker1.Value
Dim startDate = New Date(selectedDate.Year, selectedDate.Month, 1)
Dim sQuery = "SELECT Count(*) FROM riskanalysis WHERE DateTimeColumnName >= #StartDate; "
Using conn As New MySqlConnection("Your connection string")
Using cmd As New MySqlCommand(sQuery, conn)
cmd.Parameters.Add("#StartDate", MySqlDbType.DateTime).Value = startDate
conn.Open()
retVal = CInt(cmd.ExecuteScalar)
End Using
End Using
If retVal <> 0 Then
MessageBox.Show("Record Already Exist for this Month!")
Return
End If
sQuery = "INSERT INTO riskanalysis (reportdate, process, avgrisk, avgriskafterImp) VALUES (#dat, #process, #avgrisk, #riskafterimp);"
Using cn As New MySqlConnection("Your connection string")
Using cmd As New MySqlCommand(sQuery, cn)
With cmd.Parameters
.Add("#dat", MySqlDbType.DateTime).Value = selectedDate
.Add("#process", MySqlDbType.VarChar)
.Add("#avgrisk", MySqlDbType.Double)
.Add("#riskafterimp", MySqlDbType.Double)
End With
cn.Open()
For i As Integer = 0 To ProcessRiskGridView.Rows.Count - 1
cmd.Parameters("#process").Value = ProcessRiskGridView.Rows(i).Cells(0).Value
cmd.Parameters("#avgrisk") = ProcessRiskGridView.Rows(i).Cells(1).Value
cmd.Parameters("#riskafterimp") = ProcessRiskGridView.Rows(i).Cells(2).Value
cmd.ExecuteNonQuery()
Next
End Using
End Using
End Sub

How to calculate the expiration date 3 months before will be expire

I need help how to get 3 months before expiration date alert. I used mysql.
Try
Call connection()
cmd.CommandText = "select * from medicine where expiry_date < date_sub(now(), interval 3 month)"
dr = cmd.ExecuteReader
count = 0
While dr.Read
count = count + 1
End While
If count = 1 Then
pop.Image = Image.FromFile("E:\asasda.png")
pop.TitleText = "Notification Alert!!!"
pop.ContentText = "Medicine at Risk"
pop.AnimationDuration = 3000
pop.Popup()
Else
pop.Image = Image.FromFile("E:\asasda.png")
pop.TitleText = "Notification Alert!!!"
pop.ContentText = "No items for risk"
pop.AnimationDuration = 3000
pop.Popup()
End If
Catch ex As Exception
End Try
I commented our Call Connection(). It is best to keep your connections local so you can be sure they are closed and disposed.
A Using...End Using block will accomplish this even it there is an error. Also I don't see where you associated a connection to your command. The call keyword is not necessary in this case. I assume that Connection() returns a connection but your did not provide a variable to hold the connection.
Pass the Select statement and the connection directly to the constructor of the command.
You have consumed all the data you returned in the While loop. If you only only need the Count then ask for the Count and use .ExecuteScalar.
I don't see the point of the If because the if portion is identical to the else portion.
An empty Catch just swallows errors. Bad idea.
Private Sub OPCode()
Dim CountReturned As Integer
Try
'Call Connection()
Using cn As New MySqlConnection("Your connection string")
Using cmd As New MySqlCommand("select Count(*) from medicine where expiry_date < date_sub(now(), interval 3 month);", cn)
cn.Open()
CountReturned = CInt(cmd.ExecuteScalar)
End Using
End Using
If CountReturned = 1 Then
pop.Image = Image.FromFile("E:\asasda.png")
pop.TitleText = "Notification Alert!!!"
pop.ContentText = "Medicine at Risk"
pop.AnimationDuration = 3000
pop.Popup()
Else
pop.Image = Image.FromFile("E:\asasda.png")
pop.TitleText = "Notification Alert!!!"
pop.ContentText = "No items for risk"
pop.AnimationDuration = 3000
pop.Popup()
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
If you cannot get the MySql data_sub working then use vb and parameters.
Using cmd As New MySqlCommand("select Count(*) from medicine where expiry_date < #Minus3Months;", cn)
cmd.Parameters.Add("#Minus3Months", MySqlDbType.DateTime).Value = Now.AddMonths(-3)
cmd.CommandText = "select * from medicine where expiry_date < #threeMonthsAgo"
cmd.parameters.add("#threeMonthsAgo", variableWithYourDate)
You can pass in a value from VB using parameters.

MS Access 2007 DAO open recordset using a specified index

This is the first time I've asked a question although I have found the solutiion to many of my broblems here over the years.
I have a frustrating problem to which I cannot find an answer. I want to do the initial read prior to a read sequentially through a linked table opened as a dynaset DAO recordset using a specific index name as defined on the table.
My code returns error 3251 'operation is not supported...' on the .index line. No doubt there is an obvious solution (Mind you, I'm trying to avoid opening a SQL query which would be the obvious answer).
Public Function IOrdCustomerStock(CustomerID As Long, ProductID As Long, KeepRsOpen As Boolean, Optional UseIndexName As String) As Boolean
Set zcls_CS.CS_rs = CurrentDb.OpenRecordset(Name:=CS_TableName, Type:=RecordsetTypeEnum.dbOpenDynaset)
With zcls_CS.CS_rs
If Not IsMissing(UseIndexName) Then
.Index = UseIndexName
End If
.FindFirst "CS_CustomerID = " & CustomerID & " and CS_ProductID = " & ProductID
If .NoMatch Then
zcls_CS.CS_EOF = True
Else
zcls_CS.CS_EOF = False
zcls_CS.CS_ID = .Fields("[ID]")
zcls_CS.CS_CustomerID = .Fields("[CS_CustomerID]")
zcls_CS.CS_PhysSalesStock = .Fields("[CS_PhysSalesStock]")
zcls_CS.CS_ProductID = .Fields("[CS_ProductID]")
zcls_CS.CS_PurQuantityRecvd = .Fields("[CS_PurQuantityRecvd]")
zcls_CS.CS_PurUnitDesc = .Fields("[CS_PurUnitDesc]")
zcls_CS.CS_PurUnitFactor = .Fields("[CS_PurUnitFactor]")
zcls_CS.CS_SaleQuantityAlloc = .Fields("[CS_SaleQuantityAlloc]")
zcls_CS.CS_SaleQuantityOrdered = .Fields("[CS_SaleQuantityOrdered]")
zcls_CS.CS_SaleUnitDesc = .Fields("[CS_SaleUnitDesc]")
zcls_CS.CS_SaleUnitFactor = .Fields("[CS_SaleUnitFactor]")
End If
End With
If Not KeepRsOpen Then
Call IOclCustomerStock
End If
IOrdCustomerStock = Not zcls_CS.CS_EOF
End Function
Once I'd restricted the problem to linked tables, I found the following post:
https://social.msdn.microsoft.com/Forums/office/en-US/d402a8d2-0771-458c-b57e-09e2d6f0c536/trying-to-open-a-linked-table-whats-going-on?forum=accessdev
I don't pretend to understand the OpenDatabase parameters but it works. I just need to add the usual error handling to my little proof of concept:
Public Function IOksInitRsIX1CustomerStock(UseIndexName As String, CustomerID As Long, ProductID As Long) As Boolean
Set zcls_CS.CS_rs = OpenDatabase(Mid(DBEngine(0)(0).TableDefs(CS_TableName).Connect, 11)).OpenRecordset(CS_TableName)
With zcls_CS.CS_rs
zcls_CS.CS_rs.Index = UseIndexName
If (CustomerID > 0 And ProductID > 0) Then
.Seek "=", CustomerID, ProductID
Else
If CustomerID > 0 Then
.Seek "=", CustomerID
End If
End If
If .NoMatch Then
zcls_CS.CS_EOF = True
Else
zcls_CS.CS_EOF = False
zcls_CS.CS_ID = .Fields("[ID]")
zcls_CS.CS_CustomerID = .Fields("[CS_CustomerID]")
zcls_CS.CS_PhysSalesStock = .Fields("[CS_PhysSalesStock]")
zcls_CS.CS_ProductID = .Fields("[CS_ProductID]")
zcls_CS.CS_PurQuantityRecvd = .Fields("[CS_PurQuantityRecvd]")
zcls_CS.CS_PurUnitDesc = .Fields("[CS_PurUnitDesc]")
zcls_CS.CS_PurUnitFactor = .Fields("[CS_PurUnitFactor]")
zcls_CS.CS_SaleQuantityAlloc = .Fields("[CS_SaleQuantityAlloc]")
zcls_CS.CS_SaleQuantityOrdered = .Fields("[CS_SaleQuantityOrdered]")
zcls_CS.CS_SaleUnitDesc = .Fields("[CS_SaleUnitDesc]")
zcls_CS.CS_SaleUnitFactor = .Fields("[CS_SaleUnitFactor]")
End If
End With
IOksInitRsIX1CustomerStock = Not zcls_CS.CS_EOF
End Function

vb.net adding large sum on variable integer

I created a queuing system which would display multiple counters and the queue number of the customer and their service group but when I update them, all data looks like the first counter. My update function is refreshed on timer tick so every 1 second it updates the information.
Public Sub updatecountera()
openconnect()
SQLi = "SELECT `counter`, `logconcern`, `logcustcurr` FROM `access` WHERE logstatus= 1 and counter=1 "
SqlRun()
If myData.Rows.Count = 0 Then
countera.Text = "avail"
counteracust.Text = "avail"
counteraservice.Text = "avail"
Else
countera.Text = myData.Rows(0)(0)
counteracust.Text = myData.Rows(0)(1)
counteraservice.Text = myData.Rows(0)(2)
End If
closeConnect()
End Sub
Public Sub updatecounterb()
openconnect()
SQLi = "SELECT `logconcern`, `logcustcurr` FROM `access` WHERE logstatus= 1 and counter=2 "
SqlRun()
If myData1.Rows.Count = 0 Then
counterb.Text = "avail"
counterbcust.Text = "avail"
counterbservice.Text = "avail"
Else
counterb.Text = myData1.Rows(0)(0)
counterbcust.Text = myData1.Rows(0)(1)
counterbservice.Text = myData1.Rows(0)(2)
End If
closeConnect()
End Sub
Every timer tick only the information of countera shows on all counter (counterb, counterc). When I try to include mydata.clear(), it shows an error of "no data row position". How can I get all the counters to update information without compressing all info in 1 sql statement and selecting per data row since it is very messy to do that?
Edited to add SqlRun() method
yes i was missing 'counter' i added it on my counterb but it still shows identical information here is my sqlrun ():
Public Sub SqlRun()
'transfer sql connections
SQL = SQLi
myCommand.Connection = conn
myCommand.CommandText = SQL
'execute adapter commands
myAdapter.SelectCommand = myCommand
myAdapter.Fill(myData)
myAdapter.Fill(myData1)
myAdapter.Fill(mydata2)
End Sub

Editing data grabbed from a recordset

Is it possible to edit data that is grabbed from a recordset? In my case, I am trying to add quantities together so that I can get a total. So an example of what I am trying to do would be:
<%
set rs = server.CreateObject("ADODB.recordset")
totalqty = 0
do NOT while rs.EOF
totalqty = totalqty + rs("QTY")
loop
>%
Whenever I tried to do something like this, I would always get an 'Type MisMatch' Error and I'm not sure how to resolve this problem.
As always, any and all help would be appreciated.
Try to "cast" the value in the recordset like so:
CDbl( rs.fields("QTY").value )
This will cast the value to a double. If the value is null you will get en error so you have to check that first...
Or you can write a function to always get the correct type:
public function parse(value, alternative)
dim val
val = trim(value & "")
parse = alternative
if val = "" then exit function
on error resume next
select case varType(parse)
case 2, 3 'integer, long
parse = cLng(val)
case 4, 5 'single, double
parse = cdbl(val)
case 6 'currency
parse = ccur(val)
case 7 'date
parse = cDate(val)
case 11 'bool
parse = cBool(val)
case 8 'string
parse = value & ""
case else
on error goto 0
lib.throwError("type not supported. val:" & value & " alt:" & alternative)
end select
on error goto 0
end function
dim val : val = rs("QTY")
val = parse(val, 0)
' now val is always an integer (either the value from db or 0)
ulluoink's solution will work, but this is simpler...
function ToDbl(vIn, nDefault)
'Convert a variant to an integer using default where necessary
if isnull(vIn) then
ToDbl = nDefault
else
if IsNumeric(CStr(vIn)) Then
ToDbl = CDbl(vIn)
else
ToDbl = nDefault
end if
end if
end function
Then just call:
totalqty = totalqty + ToDbl(rs("QTY"), 0)