使用SqlDependency實現程式對於資料庫中表資料變化的監視
阿新 • • 發佈:2018-12-13
好久沒有寫部落格了,感覺有點生疏了。
今天和大家分享一個數據庫變化自動通知客戶端的技巧,現在還是侷限在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