2

SqlDependency クラスを使用してデータベース テーブルの変更を監視しようとしています。私は何かが欠けているに違いありませんが。オンラインで見たすべての例に従い、このサイトのすべての質問を確認しました。何が欠けているのかわかりません。サービス ブローカーを有効にし、キューとサービスを作成するためにデータベースで実行した最初のコマンドを次に示します。

CREATE QUEUE ScheduleChangeQueue
GO

CREATE SERVICE ScheduleChangeService ON QUEUE ScheduleChangeQueue ([http://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
GO

ALTER DATABASE [database] SET ENABLE_BROKER

C# 側では、プロセスを開始するために呼び出される単一の静的 Setup メソッドを持つクラスを作成しました。そのためのコードは次のとおりです。

public class SqlDependencyManager
{
    private static bool DoesUserHavePermission()
    {
        var success = false;
        try
        {
            Program.Log.Info("Retrieving SqlPermission to establish dependency...");

            var clientPermission = new SqlClientPermission(System.Security.Permissions.PermissionState.Unrestricted);

            // this will throw an error if the user does not have the permissions  
            clientPermission.Demand();

            success = true;

            Program.Log.Info("SqlPermission established. Continue setting up dependency.");
        }
        catch (Exception ex)
        {
            Program.Log.Error(ex, "SqlPermission not able to be established.");
        }

        return success;
    }

    public static void Setup()
    {
        if (!DoesUserHavePermission())
        {
            return;
        }

        var connectionString = ConfigurationManager.ConnectionStrings["ShowMakerPro"].ConnectionString;

        // You must stop the dependency before starting a new one. 
        // You must start the dependency when creating a new one. 
        SqlDependency.Stop(connectionString);
        SqlDependency.Start(connectionString);

        using (var cn = new SqlConnection(connectionString))
        {
            using (var cmd = cn.CreateCommand())
            {
                cmd.CommandType = CommandType.Text;
                //cmd.CommandText = "SELECT MAX(LastChangeTime) FROM Schedule WHERE ChannelID IN ( SELECT ID FROM Channels WHERE Type = 1 ) AND StartTime BETWEEN (GETDATE() - 7) AND (GETDATE() + 30)";
                cmd.CommandText = "SELECT LastChangeTime FROM dbo.Schedule";
                cmd.Notification = null;

                // Creates a new dependency for the SqlCommand. Then creates attaches handler for the notification of data changes
                new SqlDependency(cmd).OnChange += SqlDependency_OnChange;

                cn.Open();

                cmd.ExecuteReader();
            }
        }

        Program.Log.Info("SQL Dependency set. Now monitoring schedule table for changes.");
    }

    private static void SqlDependency_OnChange(object sender, SqlNotificationEventArgs e)
    {
        if (e.Type == SqlNotificationType.Change)
        {
            // this will remove the event handler since the dependency is only for a single notification
            ((SqlDependency)sender).OnChange -= SqlDependency_OnChange;

            ScheduleOutputterService.BuildSchedules();

            Program.Log.Info("SQL Dependency triggered schedule rebuild. Resetting SqlDependency to monitor for changes.");

            Setup();
        }
    }
}

コードが正常にセットアップされ、Subscribe に対して OnChange メソッドが 1 回起動されていることがわかりますが、その後は起動しません。手動でデータベースにアクセスし、LastChangeTime フィールドを変更して、イベントが強制的に発生することを期待していますが、何も起こりません。

誰かが私が台無しにしている場所に光を当てることができますか? これは Windows フォームでは問題なく機能するが、サービス中には問題が発生しているとオンラインで言っている人もいます。

4

1 に答える 1

5

それで、私はついに私の質問に対する答えを見つけました。この時点に到達するために行ったすべての手順をリストする必要があると考えました。私の答えを 1 か所にまとめました。

まず、私の状況では、サブスクリプションが設定されるとすぐにOnChangeイベントが発生することに気付きました。そのため、変更タイプのチェックを入れて、それらのイベントを無視できるようにしました。これらのイベントは実際に私に何かを伝えようとしていたため、これらのイベントを無視することは良いことではありませんでした。私の価値観を検索すると、次のようになりました。

http://msmvps.com/blogs/siva/archive/2011/11/22/subtle-sqldependency-notification-issue.aspx

データベース内のオプションのいくつかに問題があったに違いないことがわかったので、これは非常に価値がありました。さらに調べてみると、データベースが SQL Server 2000 互換に設定されていることがわかりました。これは 2005 年以降の機能であるため、明らかに私の最初の問題です。そこで、設定を上位バージョンに変更してみました。これはうまくいきましたが、それでも同じイベントを受け取っていることに気付きました。そこで、データベースの設定を確認したところ、Service Broker の実行に必要なオプションと一致するように設定されていないことがわかりました。ここで必要なすべてのオプション設定を確認できます。

http://msdn.microsoft.com/en-us/library/ms181122(v=SQL.100).aspx

これらすべてを調べて、いくつかの回避策を実行して適切な設定をすべて四角くしようとした後も、セットアップはまだ失敗していました。しかし、今回は更新が保存されなかったため失敗しました。クライアントが問題のテーブルにトリガーを持っていて、トリガーを実行するために使用されていたデータベース設定が、QueryNotifications を実行するために必要な設定と競合していることが判明しました。

簡単に言えば、クライアントは、使用されていたすべてのトリガーを変更したくないと判断したため、作業を断念しました。しかし、SqlDependency と ServiceBroker のトラブルシューティング方法については多くのことを学びました。私が提供したこれらのいくつかのリンクが他の誰かに役立つことを願っています. 非常に役立ついくつかのリンクがコメントに記載されていましたが、この回答でそれらを再投稿して、他の項目を確認できるようにします。

http://rusanu.com/2006/06/17/the-mysterious-notification/

http://rusanu.com/2005/12/20/troubleshooting-dialogs/

于 2013-10-02T18:38:40.523 に答える