Good afternoon everyone.
I am working on a project that uses WinForms VB.NET and MSSQL I have a requirement to use SQLDependency to monitor a table for new inserts. I have encountered a problem while testing it out. Inserting once after starting the application and I do receive the notification that something has been inserted, but after that the OnChange event just doesn't get called anymore.
Private Sub LoadOrder()
Dim objError As New AppFramework.Logging.EventLog
Dim objQuoOrders As New QuotationOrders.QuotationOrder
Try
objQuoOrders.Companyid = SystemCompanyId
objQuoOrders.Picker = GsUserName
objQuoOrders.InvType = "O"
ThreadSafe(Sub() gcOrders.DataSource = objQuoOrders.GetOrdersByPicker())
Catch ex As Exception
MessageBox.Show(ex.Message, "LoadOrder", MessageBoxButtons.OK, MessageBoxIcon.Error)
objError.LogError(SystemApplicationLogSource, "AceFinancials", ex)
End Try
End Sub
Private Sub ActivateDependency()
Dim objError As New AppFramework.Logging.EventLog
Try
If sqlConnection IsNot Nothing AndAlso sqlConnection.State = ConnectionState.Open Then sqlConnection.Close()
sqlConnection = New SqlConnection(AppFramework.Database.Connection.ConnectionString)
sqlConnection.Open()
SqlDependency.Stop(AppFramework.Database.Connection.ConnectionString)
SqlDependency.Start(AppFramework.Database.Connection.ConnectionString)
Using cmd As SqlCommand = New SqlCommand(" Select tb_quotation_notifications.notification_id, tb_quotation_notifications.notification_invid
From dbo.tb_quotation_notifications
Where tb_quotation_notifications.notification_picker_id = " & UserID &
" And tb_quotation_notifications.company_id = " & SystemCompanyId, sqlConnection)
Dim dependency As SqlDependency = New SqlDependency(cmd)
AddHandler dependency.OnChange, AddressOf dependency_OnChange
cmd.ExecuteNonQuery()
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, "ActivateDependency", MessageBoxButtons.OK, MessageBoxIcon.Error)
objError.LogError(SystemApplicationLogSource, "AceFinancials", ex)
End Try
End Sub
Private Sub dependency_OnChange(sender As Object, e As SqlNotificationEventArgs)
Dim objError As New AppFramework.Logging.EventLog
Try
If e.Info = SqlNotificationInfo.Insert Then
NotificationManager.ShowNotification(NotificationManager.Notifications(0))
LoadOrder()
ActivateDependency()
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "dependency_OnChange", MessageBoxButtons.OK, MessageBoxIcon.Error)
objError.LogError(SystemApplicationLogSource, "AceFinancials", ex)
End Try
End Sub
Private Sub ThreadSafe(method As MethodInvoker)
Dim objError As New AppFramework.Logging.EventLog
Try
If (InvokeRequired) Then
Invoke(method)
Else
method()
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "ThreadSafe", MessageBoxButtons.OK, MessageBoxIcon.Error)
objError.LogError(SystemApplicationLogSource, "AceFinancials", ex)
End Try
End Sub
If you need any more info I will update my question appropriately
I found out what the problem was with the big help of Dan Guzman.
After the OnChange event fires you need to remove the event handler and then subscribe to the event again, unlike what I was doing and that is stoping the SqlDependency and starting it again.
In my case I have done that as follows
OnChange Event
Private Sub dependency_OnChange(sender As Object, e As SqlNotificationEventArgs)
Dim objError As New AppFramework.Logging.EventLog
Try
If e.Info = SqlNotificationInfo.Insert Then
NotificationManager.ShowNotification(NotificationManager.Notifications(0))
LoadOrder()
End If
Dim dependency As SqlDependency = sender
RemoveHandler dependency.OnChange, AddressOf dependency_OnChange
ActivateDependency()
Catch ex As Exception
MessageBox.Show(ex.Message, "dependency_OnChange", MessageBoxButtons.OK, MessageBoxIcon.Error)
objError.LogError(SystemApplicationLogSource, "AceFinancials", ex)
End Try
End Sub
Subscribing event
Private Sub ActivateDependency()
Dim objError As New AppFramework.Logging.EventLog
Try
If sqlConnection IsNot Nothing AndAlso sqlConnection.State = ConnectionState.Open Then sqlConnection.Close()
sqlConnection = New SqlConnection(AppFramework.Database.Connection.ConnectionString)
sqlConnection.Open()
Using cmd As SqlCommand = New SqlCommand(" Select tb_quotation_notifications.notification_id, tb_quotation_notifications.notification_invid
From dbo.tb_quotation_notifications
Where tb_quotation_notifications.notification_picker_id = " & UserID &
" And tb_quotation_notifications.company_id = " & SystemCompanyId, sqlConnection)
Dim dependency As SqlDependency = New SqlDependency(cmd)
AddHandler dependency.OnChange, AddressOf dependency_OnChange
Using sqlReader As SqlDataReader = cmd.ExecuteReader
End Using
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, "ActivateDependency", MessageBoxButtons.OK, MessageBoxIcon.Error)
objError.LogError(SystemApplicationLogSource, "AceFinancials", ex)
End Try
End Sub
Thanks a lot have a nice day.
Edit:
I moved the SqlDependency.Start() in the form load function, and the stop in the form closing function
Related
I made two comboboxes. One of them depends on data from the other. When the first one selected index changes I need take the new value and use it to update the other. Here is what I have so far for the first combobox:
Try
Dim cmd As New SqlCommand("select * from tb_section ", connSql)
connSql.Open()
Dim dr As New SqlDataAdapter(cmd)
Dim table As New DataTable
dr.Fill(table)
compsec.DataSource = table
compsec.DisplayMember = "sec_name"
compsec.ValueMember = "sec_code"
Catch ex As Exception
MsgBox(ex.Message)
connSql.Close()
Finally
connSql.Close()
End Try
And here is code for the other combo box:
Public Sub all_group_list(sectioncode)
Try
Dim cmd As New SqlCommand("select * from tb_group where sec_code= " & sectioncode.ToString, connSql)
connSql.Open()
Dim dro As New SqlDataAdapter(cmd)
Dim table As New DataTable
dro.Fill(table)
compgroup.DataSource = table
compgroup.DisplayMember = "group_name"
compgroup.ValueMember = "group_code"
Catch ex As Exception
MsgBox(ex.Message)
connSql.Close()
Finally
connSql.Close()
End Try
End Sub
When the first combobox index changes I run this code:
Private Sub compsec_SelectedIndexChanged(sender As Object, e As EventArgs) Handles compsec.SelectedIndexChanged
connSql.Close()
all_group_list(compsec.SelectedValue.ToString)
End Sub
It's not clear what problem you're actually having, but there are several fixes in the code below. Name: don't use string concatenation to put data into an SQL command! Also, don't try to re-use the same connection object throughout an application. Only share the connection string, as sharing the same connection object interferes with the connection pooling feature in ADO.Net. Further, the DataAdapter will handle opening and closing the connection for you, and a Using block, rather than a Finally block, is the best way to be sure the connection closes if an exception is thrown.
Try
Dim ds As New DataSet
Using cn As new SqlConnection(connSql.ConnectionString), _
cmd As New SqlCommand("select sec_name, sec_code from tb_section", cn), _
da As New SqlDataAdapter(cmd)
da.Fill(ds)
End Using
compsec.DisplayMember = "sec_name"
compsec.ValueMember = "sec_code"
compsec.DataSource = ds.Tables(0)
Catch ex As Exception
MsgBox(ex.Message)
End Try
.
Public Sub all_group_list(sectioncode)
Try
Dim ds As New DataSet
Using cn As New SqlConnection(connSql.ConnectionString), _
cmd As New SqlCommand("select group_name, group_code from tb_group where sec_code= #SectionCode", cn), _
da As New SqlDataAdapter(cmd)
'Had to guess at column type/length here. Use the actual column definition from your database
cmd.Parameters.Add("#SectionCode", SqlDbType.NVarChar, 10).Value = sectioncode
da.Fill(ds)
End Using
compgroup.DisplayMember = "group_name"
compgroup.ValueMember = "group_code"
compgroup.DataSource = ds.Tables(0)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
.
Private Sub compsec_SelectedIndexChanged(sender As Object, e As EventArgs) Handles compsec.SelectedIndexChanged
all_group_list(compsec.SelectedValue.ToString())
End Sub
Time-in_Time-out GUI.
I have this image of my Time-in Time-out window. As you can see I want to delete a record of a certain employee in data grid view. I have this code.
conn = New SqlConnection(connStr)
conn.Open()
Try
Dim cmd As New SqlCommand()
cmd.Connection = conn
cmd.CommandText = "DELETE FROM timelogTB WHERE EmpNo='" & Me.dgvTimelog.CurrentRow.Cells(1).Value & "'"
Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
If rowsAffected > 0 Then
MsgBox("Record has been deleted!", MsgBoxStyle.Information, "Successful")
Else
MsgBox("Failed to delete records!", MsgBoxStyle.Exclamation, "Deleting Failed...")
End If
cmd.Dispose()
Me.dgvTimelog.Rows.Remove(Me.dgvTimelog.CurrentRow)
conn.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
The problem is that when I click 1 record for a specific date, all of the record of that employee deleted also even from previous dates. I had try putting where clause but nothing happens. And also I want to put a conditional statement if the user really want to delete the record, I have this code.
If MsgBox("Do you really want to delete this record?", MsgBoxStyle.YesNo Or MsgBoxStyle.Question, "Deleting...") = MsgBoxResult.Yes Then
MsgBox("Record deleted permanently!", MsgBoxStyle.Information, "Delete!")
but even if the user select No the record would still be deleted. Can anyone tell me what seems to be the problem. Thanks in advance!
This question is finished, try this code and it worked:
Private Sub btnDelete_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click
Try
If MsgBox("Do you really want to delete this record?", MsgBoxStyle.YesNo Or MsgBoxStyle.Exclamation, "Deleting Record...") = MsgBoxResult.Yes Then
deleteRecords()
Else
MsgBox("Record not deleted!", MsgBoxStyle.Information, "Deleting Record...")
End If
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Sub deleteRecords()
conn = New SqlConnection(connStr)
conn.Open()
Try
Dim cmd As New SqlCommand()
cmd.Connection = conn
cmd.CommandText = "DELETE FROM timelogTB WHERE LogID=#LogID"
cmd.Parameters.Add(New SqlParameter("#LogID", SqlDbType.Int, 11, "LogID"))
cmd.Parameters("#LogID").Value = dgvTimelog.CurrentRow.Cells(0).Value
Dim rowsAffected As Integer = cmd.ExecuteNonQuery()
If rowsAffected > 0 Then
MsgBox("Record deleted permanently!", MsgBoxStyle.Information, "Delete!")
End If
cmd.Dispose()
Me.dgvTimelog.Rows.Remove(Me.dgvTimelog.CurrentRow)
conn.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Thanks everyone!
i want to update my datagridview and also my database im new to vb and i dont know what im doing wrong can sombody help me?
Private Sub DataGridView_Booking_Update(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView_Booking.RowLeave
Try
con.Open()
Using cmd As New SqlCommand("UPDATE Tbl_booking SET Omschrijving = #Omschrijving, Jaar = #Jaar, Opmerking = #Opmerking ,Sortnr = #Sortnr)", con)
cmd.Parameters.Add("#Omschrijving", SqlDbType.VarChar)
cmd.Parameters.Add("#Jaar", SqlDbType.Int)
cmd.Parameters.Add("#Opmerking", SqlDbType.VarChar)
cmd.Parameters.Add("#Sortnr", SqlDbType.Int)
cmd.ExecuteNonQuery()
End Using
Catch ex As Exception
MessageBox.Show("Error while updating record on table..." & ex.Message, "Update Records")
Finally
con.Close()
End Try
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
Dim con As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\database1.accdb;Persist Security Info=False;")
con.Open()
Dim cmd As New OleDb.OleDbCommand("INSERT INTO table1(name,age,class) VALUES('John Legend','22','B.A Part 1')", con)
cmd.ExecuteNonQuery()
MsgBox("Record inserted successfully.")
con.Close()
Catch
MsgBox("Error Occured.")
End Try
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Try
Dim con As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\database1.accdb;Persist Security Info=False;")
con.Open()
Dim cmd As New OleDb.OleDbCommand("update table1 set name='John DOE',age='23',class='12th' where id='1'", con)
cmd.ExecuteNonQuery()
MsgBox("Record Updated Successfully.")
con.Close()
Catch
MsgBox("Error Occured.")
End Try
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Try
Dim con As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\database1.accdb;Persist Security Info=False;")
con.Open()
Dim cmd As New OleDb.OleDbCommand("Delete from table1 where name='John DOE'", con)
cmd.ExecuteNonQuery()
MsgBox("Record Deleted Successfully.")
con.Close()
Catch
MsgBox("Error Occured.")
End Try
End Sub
Private Sub DataGridView1_CellValueChanged(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
Me.Validate()
Me.dbDataAdapter.Update(Me.dbdataset.Tables("MyTable"))
Me.dbDataSet.AcceptChanges()
End Sub
This should be straight forward but it doesn't want to work for me..
I'm trying to populate a Datagridview on form load. The Sub below works fine if i call Populategrid() from a button once the grid is populate with the Reloadrecords & displayrecords.
Public Sub populategrid()
If Trim(Me.Text) = "CIMDETAILS" Then
da = New SqlDataAdapter("SELECT * from Interactions where [Name] like '" & txtdetect2.Text & "%' order by [IntDate] desc", SQLCon)
dsetAssets = New DataSet
da.Fill(dsetAssets, "Interactions")
dgvData.DataSource = dsetAssets.Tables("Interactions").DefaultView
Else
ReloadRecords()
DisplayRecords()
End If
Public Sub DisplayRecords()
Try
Dim da = New SqlDataAdapter("SELECT * from Interactions order by [IntDate] desc", SQLCon)
dsetAssets = New DataSet
da.Fill(dsetAssets, "Interactions")
dgvData.DataSource = dsetAssets.Tables("Interactions").DefaultView
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, Me.Text)
End Try
End Sub
Sub ReloadRecords()
Try
FillCIM("SELECT * FROM Interactions order by [IntDate] desc", dgvData)
dgvData.Columns(0).Visible = False
dgvData.Columns(1).Width = 300 ''Name''
dgvData.Columns(1).HeaderCell.Value = "Customer Name"
dgvData.Columns(2).Width = 200 ''Int type''
dgvData.Columns(2).HeaderCell.Value = "Interaction Type"
dgvData.Columns(3).Width = 170 ''Int Date''
dgvData.Columns(3).HeaderCell.Value = "Interaction Date"
dgvData.Columns(4).Width = 400 ''Remarks''
dgvData.Columns(4).HeaderCell.Value = "Remarks"
dgvData.Columns(5).Visible = False
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, Me.Text)
End Try
End Sub
Private Sub CIMDETAILS_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ReloadRecords()
DisplayRecords()
Call populategrid()
End Sub
Public Function FillCIM(ByVal Sqlstring As String, ByVal MyDataGrid As DataGridView)
Dim Constring = "Data Source=" & database & "\SQLEXPRESS; Initial Catalog = CIM; Integrated Security=true"
Dim SQLCon As New SqlConnection(Constring)
Dim SQLAdapter As New SqlDataAdapter()
Dim myDataset As New DataSet()
SQLCon.Open()
Try
SQLAdapter.SelectCommand = New SqlCommand(Sqlstring, SQLCon)
SQLAdapter.Fill(myDataset)
MyDataGrid.DataSource = myDataset.Tables(0)
Catch ex As Exception
End Try
SQLCon.Close()
SQLAdapter.Dispose()
myDataset.Dispose()
Return True
End Function
Pretty simple to get this working.
I've only just discovered there's an event after form load, which is form shown. Once i put the populategrid() sub in there it works fine.
i have a problem. when i running the project and after i click "SAVE" button, this error message will display https://www.dropbox.com/s/drpopoqi3etob3d/Presentation1.png
below is the code of the project
Imports System.Data.SqlClient
Public Class frmAddNewStaffAdmin
Dim con As SqlClient.SqlConnection
Dim dbSource As String
Dim cmd As SqlClient.SqlCommand
Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
Try
If Len(Trim(cboRole.Text)) = 0 Then
MessageBox.Show("Please select user type", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
cboRole.Focus()
Return
ElseIf Len(Trim(txtStaffID.Text)) = 0 Then
MessageBox.Show("Please enter Staff ID", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
txtStaffID.Focus()
Return
ElseIf Len(Trim(txtStaffName.Text)) = 0 Then
MessageBox.Show("Please enter Staff Name", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
txtStaffName.Focus()
Return
ElseIf Len(Trim(txtUsername.Text)) = 0 Then
MessageBox.Show("Please enter Username", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
txtUsername.Focus()
Return
ElseIf Len(Trim(txtPassword.Text)) = 0 Then
MessageBox.Show("Please enter Password", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
txtPassword.Focus()
Return
End If
dbSource = "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\HMS.mdf;Integrated Security=True;User Instance=True"
con = New SqlConnection(dbSource)
con.Open()
Dim sql As String = "INSERT INTO [User] ([Staff_ID], [Staff_Role], [Staff_Name], [Username], [Password]) VALUES (#StaffID, #Role, #StaffName, #Username, #Password) "
cmd.Connection = con
cmd.ExecuteNonQuery()
cmd.Parameters.AddWithValue("#Staff_ID", txtStaffID.Text)
cmd.Parameters.AddWithValue("#Role", cboRole.Text)
cmd.Parameters.AddWithValue("#StaffName", txtStaffName.Text)
cmd.Parameters.AddWithValue("#Username", txtUsername.Text)
cmd.Parameters.AddWithValue("#Password", txtPassword.Text)
cmd = New SqlCommand(sql)
MessageBox.Show("Successfully saved", "Record", MessageBoxButtons.OK, MessageBoxIcon.Information)
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
Me.Hide()
frmStaffAdmin.Show()
End Sub
End Class
Your code is not correctly ordered. You use the SqlCommand before its initialization and of course this results in the mentioned error
dbSource = "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\HMS.mdf;Integrated Security=True;User Instance=True"
con = New SqlConnection(dbSource)
con.Open()
Dim sql As String = "INSERT INTO [User] ([Staff_ID], [Staff_Role], [Staff_Name], [Username], [Password]) VALUES (#StaffID, #Role, #StaffName, #Username, #Password) "
cmd = New SqlCommand(sql)
cmd.Connection = con
cmd.Parameters.AddWithValue("#StaffID", txtStaffID.Text)
cmd.Parameters.AddWithValue("#Role", cboRole.Text)
cmd.Parameters.AddWithValue("#StaffName", txtStaffName.Text)
cmd.Parameters.AddWithValue("#Username", txtUsername.Text)
cmd.Parameters.AddWithValue("#Password", txtPassword.Text)
cmd.ExecuteNonQuery()
MessageBox.Show("Successfully saved", "Record", MessageBoxButtons.OK, MessageBoxIcon.Information)
con.Close()
Moved the initialization of the SqlCommand before its first usage and moved the ExecuteNonQuery as the last instruction