简体   繁体   English

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

[英]SqlDependency doesn't fire OnChange event when dataset is changed

I'm new to the concept of query notifications with SQL Server and it's going to take some time for me to wrap my head around it. 我对使用SQL Server查询通知的概念是陌生的,需要花一些时间来解决这个问题。

My objective is to create a Windows service application that is notified when a change has been made to a SQL Server table. 我的目标是创建一个Windows服务应用程序,当对SQL Server表进行更改时会收到通知。 I followed this guide which was helpful in getting me started. 我遵循了指南,这对帮助我入门很有帮助。

However I'm not able to get the expected result. 但是我无法获得预期的结果。 The OnStart() method in my windows service app looks like so: 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);
        }
}

The event SqlDependency is subscribed to, looks like so: 订阅了SqlDependency事件,如下所示:

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

The OnStop() method looks like so: OnStop()方法如下所示:

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

I have ENABLE_BROKER set to true in my database. 我在数据库中将ENABLE_BROKER设置为true。 The end result is, The service runs and the followings logs are created: 最终结果是,该服务运行,并创建了以下日志:

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

However when I insert new data into the table, the OnChange() event doesn't fire and no new log is created. 但是,当我将新数据插入表中时,不会触发OnChange()事件,也不会创建新日志。 Also when I stop and start the service again, the OnChange() is triggered even though there was no new data inserted. 同样,当我停止并再次启动该服务时,即使没有插入新数据,也会触发OnChange()

Can anyone help me understand the process? 谁能帮助我了解这一过程?

The SqlDependency is removed after the event fires so you need to execute the command again with the dependency. 事件触发后将删除SqlDependency,因此您需要再次使用依赖项执行命令。 Below is a console app example that will subscribe again unless the notification was due to an error. 下面是一个控制台应用程序示例,除非由于错误通知,否则该示例将再次订阅。

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");
            }

        }


    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM