0

基本的に私のコードはここに基づいています 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 がイベントを発生させません。

4

2 に答える 2

1

ここでの主な問題は、各データアクセスメソッドを呼び出し.Stopてから、.Startメソッドにアクセスするたびに依存関係をキャンセルして再開することだと思います。

アプリケーションの開始時に1回だけ呼び出す必要があり.Start、同様にアプリケーションの.Stop終了時に呼び出す必要があります。

たとえば、Webアプリケーションでは、これに最適な場所はGlobal.asaxApplication_StartApplication_Endイベントです。

于 2012-02-08T21:29:21.800 に答える
1

私はあなたが正しいと思います、私は同じ問題に遭遇しました。SqlDependency.Start(connectionString) への 2 回目の呼び出しは、New SqlDependency(cmd) の後でさえ、既存の初期の既定の Service Broker サービスとキューを置き換えました。

Service Broker は、サービス名とキュー名の一部として GUID を使用して、開始ごとに既定のサービスとキューを作成します: Service{GUID} と Queue{GUID} - ただし、使用可能な既定のサービス/キューのペアは 1 つだけのようです。

これを確認するには、最初の Start の直後と 2 番目の Start の直後にブレークポイントを配置します。SQL Server に移動し、dBase に移動して、Service Broker/Services および Service Broker/Queues フォルダーを確認します。Services および Queues フォルダーを右クリックし、2 番目のブレークポイントの後に更新を選択する必要があります。

于 2014-01-31T21:18:37.630 に答える