SqlDependency
SqlDependency 是用來監聽資料庫裡的 Table 資料是否有變動,
當資料有變動時,則會觸發 SqlDependency 所指定的 Handler,
去作後續處理。以下為範例展示。
建立一個範例資料庫
CREATE DATABASE MYDATABASE; GO USE MYDATABASE; GO CREATE TABLE TABLE_NAME ( id_a INT NULL ,name_a NVARCHAR(50) NULL ) GO INSERT TABLE_NAME VALUES (1, 'Tom'); INSERT TABLE_NAME VALUES (2, 'Bob'); INSERT TABLE_NAME VALUES (3, 'Tim');
開啟 Server Broker
ALTER DATABASE MYDATABASE SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE;
Form1.Designer.cs 內容為
namespace WindowsFormsApp1
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnStart = new System.Windows.Forms.Button();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// btnStart
//
this.btnStart.Location = new System.Drawing.Point(12, 488);
this.btnStart.Name = "btnStart";
this.btnStart.Size = new System.Drawing.Size(244, 23);
this.btnStart.TabIndex = 0;
this.btnStart.Text = "開始監聽";
this.btnStart.UseVisualStyleBackColor = true;
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
//
// dataGridView1
//
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(12, 12);
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.RowTemplate.Height = 24;
this.dataGridView1.Size = new System.Drawing.Size(244, 470);
this.dataGridView1.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(270, 522);
this.Controls.Add(this.dataGridView1);
this.Controls.Add(this.btnStart);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button btnStart;
private System.Windows.Forms.DataGridView dataGridView1;
}
}
Form1.cs 內容為
using System;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
string ConnectionString = "Data Source=" + "DESKTOP-xxx\\SQLEXPRESS" + ";Initial Catalog=" + "MYDATABASE" + ";User ID=" + "sa" + ";Password=" + "xxx";
public Form1()
{
InitializeComponent();
}
private void btnStart_Click(object sender, EventArgs e)
{
//SqlDependency 註冊 ConnectionString
SqlDependency.Start(ConnectionString);
//建立 SqlDependency 監聽與處置
SqlDependencyWatch();
//先對dataGridView1做更新
RefreshTable();
}
private void SqlDependencyWatch()
{
//dependency固定寫法,藉由 dependency 查詢整張 table ,來監聽該張 table 資料是否有異動
string sSQL = "select id_a,name_a from [dbo].[TABLE_NAME]";
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(sSQL, connection))
{
command.CommandType = CommandType.Text;
connection.Open();
//將command放進SqlDependency
SqlDependency dependency = new SqlDependency(command);
//當發生資料庫有變動時,dependency要做什麼處置
dependency.OnChange += new OnChangeEventHandler(SQLTableOnChange);
//執行一次監聽
SqlDataReader sdr = command.ExecuteReader();
}
}
}
private void SQLTableOnChange(object sender, SqlNotificationEventArgs e)
{
//觸發後再開啟一次監聽事件
SqlDependencyWatch();
//並對dataGridView1做更新
RefreshTable();
}
private void RefreshTable()
{
string sSQL = "select id_a,name_a from [dbo].[TABLE_NAME]";
DataTable datatable = new DataTable();
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
connection.Open();
using (SqlCommand cmd = new SqlCommand(sSQL, connection))
{
using (SqlDataAdapter dr = new SqlDataAdapter(sSQL, connection))
{
dr.Fill(datatable);
//這邊要注意,因為SqlDependency是屬於另外個執行緒
//所以要使用Invoke來做UI的更新
Action helloDelegate = delegate () { dataGridView1.DataSource = datatable; };
this.Invoke(helloDelegate);
}
}
}
}
}
}
當開始監聽時,如下畫面
這時我們在 SSMS 下 SQL 指令,讓資料變動一下,以便去觸發 SqlDependency handler
INSERT TABLE_NAME VALUES (4, 'Kiki');
成功觸發 SqlDependency handler,做了即時更新畫面
小結:
SqlDependency 的使用,主要有五步驟:
1、開啟 Server Broker。
2、藉由 SqlDependency 實體去註冊 ConnectionString。
3、將所要監聽目的 Table 的指令 command 放進 SqlDependency 實體。
4、指定 SqlDependency 實體的 OnChangeEventHandler 之觸發處理方法。
5、執行一次監聽。
參考資料: