使用SqlDependency实现程序对于数据库中表数据变化的监视

好久没有写博客了,感觉有点生疏了。

今天和大家分享一个数据库变化自动通知客户端的技巧,现在还是局限在sqlServer上的使用,在文章最后附上源码

今天的主角就是SqlDependency--实现数据库中对于某一张表的监视,好了。废话不多说了,开始搞,今天我新建了个简单的WPF项目如下:

1、首先需要对数据库的设置:

 **  1、设置某个数据库代理的回滚 
 *      ALTER DATABASE [test] SET NEW_BROKER WITH ROLLBACK IMMEDIATE; 
 *  2、设置某个数据库的代理 
 *      ALTER DATABASE [test] SET ENABLE_BROKER; 
 *  3、查询某个数据库是否已经启动了代理 
 *      SELECT name,is_broker_enabled FROM sys.databases WHERE name = 'yaozheng'
 *      is_broker_enabled 为0表示未启动代理 1表示已启动代理  

2、开始c#代码 ,初始化方法中启动监听器

        /// <summary>
        /// 初始化
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
            // 启动侦听器来接收来自通过连接字符串指定的 SQL Server 实例的依赖项更改通知。
            SqlDependency.Start(_connStr);
            SelectData();
        }

3、写一个简单的数据库查询SelectData,重点就是

                    SqlDependency dependency = new SqlDependency(command);
                    // 事件注册,这是核心
                    dependency.OnChange += new OnChangeEventHandler(Dependency_OnChange);

详细如下:

        /// <summary>
        /// 数据库查询操作
        /// </summary>
        private static void SelectData()
        {
            using (SqlConnection connection = new SqlConnection(_connStr))
            {
                //依赖是基于某一张表的,而且查询语句只能是简单查询语句,不能带top或*,同时必须指定所有者,即类似[dbo].[] 
                string cmdText = "SELECT [ID],[Name],[Age] from dbo.Test_Table where [Age] = 1";
                using (SqlCommand command = new SqlCommand(cmdText, connection))
                {
                    command.CommandType = CommandType.Text;
                    connection.Open();
                    SqlDependency dependency = new SqlDependency(command);
                    // 事件注册,这是核心
                    dependency.OnChange += new OnChangeEventHandler(Dependency_OnChange);

                    SqlDataReader sdr = command.ExecuteReader();
                    Console.WriteLine();
                    while (sdr.Read())
                    {
                        Console.WriteLine("Id:{0}\\Name:{1}\\Age:{2}", sdr["ID"].ToString(), sdr["Name"].ToString(), sdr["Age"].ToString());
                    }
                    sdr.Close();
                }
            }
        }
4、实现Dependency_OnChange方法,在数据库中数据发生变化时,重新获取
        /// <summary>
        /// 具体事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void Dependency_OnChange(object sender, SqlNotificationEventArgs e)
        {
            // 只有数据发生变化时,才重新获取数据 
            if (e.Type == SqlNotificationType.Change)
            {
                SelectData();
            }
        }

 5、WPF还有一个资源的自动释放,关闭监听

       
        /// <summary>
        /// 注意资源的释放 关闭监听
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closed(object sender, EventArgs e)
        {
            SqlDependency.Stop(_connStr);
        }

 

以上操作就可以实现数据库数据变化时自动触发 SelectData() 方法。

以下重点说下注意事项,是我在实际使用过程中踩过的坑,希望大家可以避免:

* 1、应用程序开始或者结束时,必须相应的开始或者停止对SQL Server的监控。
* 2、只有SQL语句中需要查询的字段才会被监控,没有查询的数据发生变化时,并不会触发dependency_OnChange事件。
* 3、查询语句只能是简单查询语句,不能带top,不能使用*,不能使用函数包括聚合函数,包括where子查询
* 4、不能使用外连接、自连接、不能使用临时表、不能用变量、不能用试图、不能跨表、表名前必须加类型dbo的前缀
* 5、待查询的字段的数据也不能太复杂。测试时,有个字段保存Json格式的数据。如果将这个字段也写入到SQL语句中,则不会被监控到。
* 6、OnChange只能提供一次通知,如果需要重新发起,需要重新添加事件

 最后附上源码

源码:https://github.com/YaoHigh/SqlDependencyTest

posted @ 2018-12-13 23:12  思明  阅读(2363)  评论(1编辑  收藏  举报