更改数据集时,SqlDependency 不会触发 OnChange 事件

SqlDependency doesn't fire OnChange event when dataset is changed

我对 SQL 服务器的查询通知概念还很陌生,我需要一些时间来理解它。

我的 objective 是创建一个 Windows 服务应用程序,当对 SQL 服务器 table 进行更改时,该应用程序会收到通知。我遵循了 this 指南,这对我入门很有帮助。

但是我无法获得预期的结果。我的 windows 服务应用程序中的 OnStart() 方法如下所示:

protected override void OnStart(string[] args)
{
        eventLog1.WriteEntry("Service Started");

        serviceRun = false;

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

        try
        {
            perm.Demand();
            eventLog1.WriteEntry("permission granted");
        }
        catch (System.Exception)
        {
            eventLog1.WriteEntry("permission denied");
        }

        try
        {
            connstr = "Data Source=THSSERVER-LOCAL;Initial Catalog=ET;User ID=mujtaba;Password=ths123";

            connection = new SqlConnection(connstr);

            SqlCommand command = new SqlCommand("select * from dbo.Customer_FileUploads", 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 += Dependency_OnChange;

            SqlDependency.Start(connstr);

            connection.Open();

            // Execute the command.
            using (SqlDataReader reader = command.ExecuteReader())
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        //eventLog1.WriteEntry("reading data");
                    }
                }
                else
                {
                    eventLog1.WriteEntry("No rows found.");
                }
                reader.Close();
            }
        }
        catch (Exception e)
        {
            eventLog1.WriteEntry("Error Message: " + e.Message);
        }
}

事件 SqlDependency 已订阅,如下所示:

private void Dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
    // Handle the event.
    eventLog1.WriteEntry("data changed");
}

OnStop() 方法如下所示:

protected override void OnStop()
{
        SqlDependency.Stop(connstr);
        connection.Close();
        eventLog1.WriteEntry("In onStop.");
}

我在我的数据库中将 ENABLE_BROKER 设置为 true。最终结果是,服务运行并创建以下日志:

"Service Started"
"permission granted"
"data changed"

然而,当我将新数据插入 table 时,OnChange() 事件没有触发,也没有创建新日志。此外,当我停止并再次启动服务时,即使没有插入新数据,也会触发 OnChange()

谁能帮我理解这个过程?

SqlDependency 在事件触发后被删除,因此您需要使用依赖项再次执行命令。下面是一个控制台应用程序示例,它将再次订阅,除非通知是由于错误引起的。

using System;
using System.Data;
using System.Data.SqlClient;

namespace SqlDependencyExample
{
    class Program
    {

        static string connectionString = @"Data Source=.;Initial Catalog=YourDatabase;Application Name=SqlDependencyExample;Integrated Security=SSPI";

        static void Main(string[] args)
        {

            SqlDependency.Start(connectionString);

            getDataWithSqlDependency();

            Console.WriteLine("Waiting for data changes");
            Console.WriteLine("Press enter to quit");
            Console.ReadLine();

            SqlDependency.Stop(connectionString);

        }

        static DataTable getDataWithSqlDependency()
        {

            using (var connection = new SqlConnection(connectionString))
            using (var cmd = new SqlCommand("SELECT Col1, Col2, Col3 FROM dbo.MyTable;", connection))
            {

                var dt = new DataTable();

                // Create dependency for this command and add event handler
                var dependency = new SqlDependency(cmd);
                dependency.OnChange += new OnChangeEventHandler(onDependencyChange);

                // execute command to get data
                connection.Open();
                dt.Load(cmd.ExecuteReader(CommandBehavior.CloseConnection));

                return dt;

            }

        }

        // Handler method
        static void onDependencyChange(object sender,
           SqlNotificationEventArgs e)
        {

            Console.WriteLine($"OnChange Event fired. SqlNotificationEventArgs: Info={e.Info}, Source={e.Source}, Type={e.Type}.");

            if ((e.Info != SqlNotificationInfo.Invalid)
                && (e.Type != SqlNotificationType.Subscribe))
            {
                //resubscribe
                var dt = getDataWithSqlDependency();

                Console.WriteLine($"Data changed. {dt.Rows.Count} rows returned.");
            }
            else
            {
                Console.WriteLine("SqlDependency not restarted");
            }

        }


    }
}