基本上我的代码基于此处 http://www.dreamincode.net/forums/topic/185244-using-sqldependency-to-monitor-sql-database-changes/
目前的情况是我有2个表希望监控,所以我简单地复制另一个类似的代码与第一个sqldependancy,但它失败了,似乎最新的sqldependancy将取代以前的sqldependancy函数。
这是我的代码
Public Sub GetNames()
If Not DoesUserHavePermission() Then
Return
End If
lbQueue.Items.Clear()
' You must stop the dependency before starting a new one.
' You must start the dependency when creating a new one.
Dim connectionString As String = GetConnectionString()
SqlDependency.Stop(connectionString)
SqlDependency.Start(connectionString)
Using cn As SqlConnection = New SqlConnection(connectionString)
Using cmd As SqlCommand = cn.CreateCommand()
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT PatientID FROM dbo.[patient_queue]"
cmd.Notification = Nothing
' creates a new dependency for the SqlCommand
Dim dep As SqlDependency = New SqlDependency(cmd)
' creates an event handler for the notification of data changes in the database
AddHandler dep.OnChange, AddressOf dep_onchange
cn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader()
While dr.Read()
lbQueue.Items.Add(dr.GetInt32(0))
doctor.lbqueue.items.add(dr.GetInt32(0))
End While
End Using
End Using
End Using
End Sub
Private Sub dep_onchange(ByVal sender As System.Object, ByVal e As System.Data.SqlClient.SqlNotificationEventArgs)
' this event is run asynchronously so you will need to invoke to run on the UI thread(if required)
If Me.InvokeRequired Then
lbQueue.BeginInvoke(New MethodInvoker(AddressOf GetNames))
My.Computer.Audio.PlaySystemSound(Media.SystemSounds.Asterisk)
Else
GetNames()
End If
' this will remove the event handler since the dependency is only for a single notification
Dim dep As SqlDependency = DirectCast(sender, SqlDependency)
RemoveHandler dep.OnChange, AddressOf dep_onchange
End Sub
Public Sub GetMedID()
If Not DoesUserHavePermission() Then
Return
End If
lbMedQueue.Items.Clear()
' You must stop the dependency before starting a new one.
' You must start the dependency when creating a new one.
Dim connectionString As String = GetConnectionString()
SqlDependency.Stop(connectionString)
SqlDependency.Start(connectionString)
Using cn As SqlConnection = New SqlConnection(connectionString)
Using cmd As SqlCommand = cn.CreateCommand()
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT RecordID FROM dbo.[medicine_queue]"
cmd.Notification = Nothing
' creates a new dependency for the SqlCommand
Dim dep As SqlDependency = New SqlDependency(cmd)
' creates an event handler for the notification of data changes in the database
AddHandler dep.OnChange, AddressOf dep_onchange2
cn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader()
While dr.Read()
lbMedQueue.Items.Add(dr.GetInt32(0))
End While
End Using
End Using
End Using
End Sub
Private Sub dep_onchange2(ByVal sender As System.Object, ByVal e As System.Data.SqlClient.SqlNotificationEventArgs)
' this event is run asynchronously so you will need to invoke to run on the UI thread(if required)
If Me.InvokeRequired Then
lbMedQueue.BeginInvoke(New MethodInvoker(AddressOf GetMedID))
My.Computer.Audio.PlaySystemSound(Media.SystemSounds.Asterisk)
Else
GetMedID()
End If
' this will remove the event handler since the dependency is only for a single notification
Dim dep As SqlDependency = DirectCast(sender, SqlDependency)
RemoveHandler dep.OnChange, AddressOf dep_onchange2
End Sub
最后我在加载表单上调用了GetNames,GetMedID,它运行正常,只是GetMedID正在运行,并且GetNames在onchanged时不会触发事件。
答案 0 :(得分:1)
我认为这里的主要问题是您在每个数据访问方法中调用.Stop
然后调用.Start
,因此每次访问方法时都会取消并重新启动依赖项。
您只需在应用程序启动时调用.Start
一次,并在结束时调用.Stop
。
例如,在Web应用程序中,最佳位置是Global.asax Application_Start
和Application_End
事件。
答案 1 :(得分:1)
我认为你是对的,我遇到了同样的问题。第二次调用SqlDependency.Start(connectionString),即使在New SqlDependency(cmd)之后,也替换了现有的初始默认Service Broker服务和队列。
Service Broker在每个Start上使用GUID作为服务和队列名称的一部分创建默认服务和队列:服务{GUID}和队列{GUID} - 但似乎只有一个defualt服务/队列对可用
您可以通过在第一次开始后立即和第二次开始后立即设置断点来验证这一点。转到SQL Server,转到你的dBase并查看 Service Broker / Services和Service Broker / Queues文件夹。您需要右键单击“服务和队列”文件夹,然后在第二个断点后选择“刷新”