好久沒有寫博客了,感覺有點生疏了。
今天和大家分享一個數據庫變化自動通知客戶端的技巧,現在還是局限在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