好久没有写博客了,感觉有点生疏了。
今天和大家分享一个数据库变化自动通知客户端的技巧,现在还是局限在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