ASP.NET SqlCacheDependency 類別 (System.Web.Caching.SqlCacheDependency) 與 OutputCache 指示詞會使用 SqlDependency 實現自動通知功能。若 ADO.NET 客戶端需對查詢通知擁有更多控制權,可使用 SqlNotificationRequest 並手工處理 Service Broker 佇列,實現自訂處理邏輯。深入解釋 Service Broker 超出本文範圍,參考 A First Look at SQL Server 2005 for Developers 範例章節與 Roger Wolter 文章 A First Look at SQL Server 2005 Service Broker。
繼續前,務必明確:當結果集改變時,每個 SqlNotificationRequest 或 SqlDependency 只收到一條通知訊息。不管資料改變因 INSERT 插入、DELETE 刪除一或多列、UPDATE 更新一或多列,通知訊息完全相同,通知中不包含任何關於改變列數或哪些列被改變的資訊。當快取物件或用戶應用程式收到這條資料改變訊息時只有一種選擇:重新整理整個結果集或重新註冊通知。您不會收到多條訊息,該條訊息引發後,資料庫中用戶訂閱也不存在了。此外查詢通知框架工作前提:為多種不同事件發送通知總比根本不通知好。因此不僅結果集改變時發送通知,刪除或修改結果集引用表、回收資料庫、其他原因也會發送通知。快取或程式對通知回應通常相同:重新整理快取資料並重新註冊通知。
現在我們了解所有相關概念與語義,接著從三個角度深入研究查詢通知如何運作:
SqlClient 的 SqlDependency 與 SqlNotificationRequest 如何在客戶層/中間層工作?SqlDependency?伺服器層級,SQL Server 批次處理客戶端發送查詢。每個查詢 (可視為 SqlCommand.CommandText 屬性) 只能包含一個批次,雖每個批次可包含多個 T-SQL 陳述式。SqlCommand 還可執行預存程序或使用者定義函數,這些物件也可包含多個 T-SQL 陳述式。在 SQL Server 2005 中,客戶端發送查詢還包含其他三項資訊:用於投遞通知的 Service Broker service、通知識別碼 (字串)、通知逾時值。若查詢請求存在此三項資訊且查詢包含 SELECT 或 EXECUTE 陳述式,SQL Server 將「監視」該查詢產生所有結果集是否因其他 SQL Server 工作階段而改變。若產生多個結果集 (如執行某預存程序),SQL Server 將「監視」所有結果集。
所謂「監視」結果集是指什麼?SQL Server 如何完成該任務?對結果集變更偵測是 SQL Server 資料庫引擎一部分,使用 SQL Server 2000 中用於索引檢視同步的變更偵測機制。SQL Server 2000 中,Microsoft 引入索引檢視概念。SQL Server 中檢視包含對單張或多張表欄位查詢。每個檢視物件有名稱,可像使用表名那樣使用檢視名稱:
CREATE VIEW WestCoastAuthors
AS
SELECT * FROM authors
WHERE state IN ('CA', 'WA', 'OR')
現在可使用檢視,就像在查詢中使用表:
SELECT au_id, au_lname FROM WestCoastAuthors
WHERE au_lname LIKE 'S%'
大多數程式設計師熟悉檢視,但可能不熟悉索引檢視。非索引檢視中,檢視資料不作為獨立副本儲存;每次使用檢視時,檢視包含查詢將被執行。因此上例中,將執行取得 WestCoastAuthors 結果集查詢,再透過條件判定找出想要的 WestCoastAuthors。索引檢視則儲存資料副本,故若將 WestCoastAuthors 建為索引檢視,我們擁有兩份 authors 資料。現在可透過兩種方式更新資料,或透過索引檢視、或透過原始表。SQL Server 因此需對兩份實體資料儲存變化偵測,將一處變更套用到另一處。此變更偵測機制與資料庫引擎處理查詢通知時使用機制相同。
因變更偵測此實作方式,並非所有檢視都可建立索引。那些索引檢視限制條件對查詢通知同樣生效。例如:以上面方式撰寫的 WestCoastAuthors 檢視就不能建立索引。要在檢視上建立索引,檢視定義必須使用兩部分命名法則,且必須顯式列出結果集所有欄位名。為建立索引修改檢視定義:
CREATE VIEW WestCoastAuthors
WITH SCHEMABINDING
AS
SELECT au_id, au_lname, au_fname, address, city, state, zip, phone
FROM dbo.authors
WHERE state IN ('CA', 'WA', 'OR')
只有遵循索引檢視規則的查詢才可使用通知。注意:儘管使用相同機制判定查詢結果集是否發生改變,但查詢通知不會導致 SQL Server 建立資料副本,而索引檢視會。可在 SQL Server 2005 Books Online 找到索引檢視系列規則。若提交附帶通知請求但違背規則查詢,SQL Server 會立即發出原因為「無效查詢」通知。通知發布到哪裡?
SQL Server 2005 使用 Service Broker 傳遞通知。Service Broker 是 SQL Server 內建非同步訊息佇列功能。查詢通知將使用 Service Broker SERVICE。此處 SERVICE 指非同步訊息目的地;可強制要求訊息必須遵循稱為契約的一組規則。每個 Service Broker SERVICE 始終與某個佇列 (即實體訊息目的地) 關聯。查詢通知契約內建於 SQL Server,名稱為 https://schemas.microsoft.com/SQL/Notifications/PostQueryNotification。
注意:儘管契約在 SQL Server 中物件名看似 URL,但與該位置無任何關聯。它只是物件名,就像 dbo.authors 是表名。
總之,查詢通知訊息目的地可以是任何 SERVICE,只要該 SERVICE 支援相應契約。用 SQL DDL 定義 service 陳述式:
CREATE QUEUE mynotificationqueue
CREATE SERVICE myservice ON QUEUE mynotificationqueue
([https://schemas.microsoft.com/SQL/Notifications/PostQueryNotification])
GO