SqlDependency を使用した変更の検出

クエリ結果が最初に取得されたクエリ結果と異なることを検出するために、SqlDependency オブジェクトを SqlCommand に関連付けることができます。 OnChange イベントにデリゲートを割り当てることもできます。これは、関連付けられたコマンドの結果が変更されたときに実行されます。 コマンドを実行する前に、SqlDependency をコマンドに関連付ける必要があります。 また、HasChangesSqlDependency プロパティを使用しても、データが最初に取得されて以降にクエリ結果が変化したかどうかを判別できます。

セキュリティの考慮事項

指定されたコマンドについて基になるデータが変更されたという通知を受け取るために、依存関係を持つインフラストラクチャでは SqlConnection が呼び出されると、Start が開かれることを利用します。 クライアントが SqlDependency.Start の呼び出しを開始できるかどうかは、SqlClientPermission を使用し、コード アクセス セキュリティ属性を利用することで制御します。 詳しくは、「クエリ通知の有効化」および「コード アクセス セキュリティと ADO.NET」をご覧ください。

次の手順では、依存関係を宣言し、コマンドを実行し、結果セットが変更されたときに通知を受け取る方法について説明します。

  1. サーバーへの SqlDependency 接続を開始します。

  2. サーバーに接続して Transact-SQL ステートメントを定義するための SqlConnection および SqlCommand オブジェクトを作成します。

  3. 新しい SqlDependency オブジェクトを作成するか、既存のオブジェクトを使用して、それを SqlCommand オブジェクトにバインドします。 内部では、これによって SqlNotificationRequest オブジェクトが作成され、必要に応じてコマンド オブジェクトにバインドされます。 この通知要求には、この SqlDependency オブジェクトを一意に識別する内部識別子が含まれます。 また、これにより、クライアント リスナーがまだアクティブになっていない場合に起動されます。

  4. イベント ハンドラーを SqlDependency オブジェクトの OnChange イベントにサブスクライブします。

  5. SqlCommand オブジェクトの任意の Execute メソッドを使用して、コマンドを実行します。 コマンドは通知オブジェクトにバインドされているため、サーバーで通知を生成する必要があることが認識され、キュー情報が依存関係キューを指します。

  6. サーバーへの SqlDependency 接続を停止します。

その後ユーザーが基になるデータを変更した場合、Microsoft SQL Server でその変更に対して保留中の通知があることが検出され、SqlDependency.Start を呼び出して作成された、基になる SqlConnection を介して処理され、クライアントに転送される通知が送信されます。 クライアント リスナーで、無効化メッセージが受信されます。 次にクライアント リスナーで、関連付けられている SqlDependency オブジェクトが検索され、OnChange イベントが起動されます。

次のコード フラグメントに、サンプル アプリケーションの作成に利用されるデザイン パターンを示します。

Sub Initialization()
    ' Create a dependency connection.
    SqlDependency.Start(connectionString, queueName)
End Sub

Sub SomeMethod()
    ' Assume connection is an open SqlConnection.
    ' Create a new SqlCommand object.
    Using command As New SqlCommand( _
      "SELECT ShipperID, CompanyName, Phone FROM dbo.Shippers", _
      connection)

        ' Create a dependency and associate it with the SqlCommand.
        Dim dependency As New SqlDependency(command)
        ' Maintain the reference in a class member.
        ' Subscribe to the SqlDependency event.
        AddHandler dependency.OnChange, AddressOf OnDependencyChange

        ' Execute the command.
        Using reader = command.ExecuteReader()
            ' Process the DataReader.
        End Using
    End Using
End Sub

' Handler method
Sub OnDependencyChange(ByVal sender As Object, _
    ByVal e As SqlNotificationEventArgs)
    ' Handle the event (for example, invalidate this cache entry).
End Sub

Sub Termination()
    ' Release the dependency
    SqlDependency.Stop(connectionString, queueName)
End Sub
void Initialization()
{
    // Create a dependency connection.
    SqlDependency.Start(connectionString, queueName);
}

void SomeMethod()
{
    // Assume connection is an open SqlConnection.

    // Create a new SqlCommand object.
    using (SqlCommand command=new SqlCommand(
        "SELECT ShipperID, CompanyName, Phone FROM dbo.Shippers",
        connection))
    {

        // Create a dependency and associate it with the SqlCommand.
        SqlDependency dependency=new SqlDependency(command);
        // Maintain the reference in a class member.

        // Subscribe to the SqlDependency event.
        dependency.OnChange+=new
           OnChangeEventHandler(OnDependencyChange);

        // Execute the command.
        using (SqlDataReader reader = command.ExecuteReader())
        {
            // Process the DataReader.
        }
    }
}

// Handler method
void OnDependencyChange(object sender,
   SqlNotificationEventArgs e )
{
  // Handle the event (for example, invalidate this cache entry).
}

void Termination()
{
    // Release the dependency.
    SqlDependency.Stop(connectionString, queueName);
}

関連項目