程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> ADO.NET 2.0中的查詢通知(5)

ADO.NET 2.0中的查詢通知(5)

編輯:關於C語言

使用SqlNotificationRequest的強大之處(當然也包括額外的工作)就是由您自己等待和處理查詢通知。如果您使用SqlDependency,那麼在接收到查詢通知之前您甚至無需連接數據庫。事實上不需要為了接收SqlNotificationRequest的通知而進行等待;可以每隔一段時間輪詢一次消息隊列。SqlNotificationRequest另一個用處就是編寫一個特別的應用程序,即使通知已經激活了,該應用程序也不會運行。當應用程序啟動後,它將連接到消息隊列並決定緩存中(由於上次運行應用程序)哪些內容是無效的。

探討一下這樣的應用程序,它們為了等待一條通知需要花費好幾個小時或者幾天,這種應用程序向我們提出了問題: “如果數據不發生改變,那麼通知何時消失呢?” 唯一可以導致通知消失的情況(例如,清理了數據庫的訂閱表)就是通知被引發或者通知過期。數據庫管理員如果為那些始終留在數據庫中的訂閱(因為它們會使用SQL資源並且增加查詢和數據更新的成本)而惱火的話,可以在SQL Server中手動地清理通知。首先查詢SQL Server 2005動態視圖,找出那些不想要的通知訂閱,然後使用下面的命令刪除它們:

-- look at all subscriptions
SELECT * FROM sys.dm_qn_subscriptions
-- pick the ID of the subscription that you want, then
-- say its ID = 42
KILL QUERY NOTIFICATION SUBSCRIPTION 42

在ASP.Net中使用SqlCacheDependency

通知功能還被連接到ASP.NET的Cache類中。ASP.NET 2.0中CacheDependency類可以派生子類,其中SqlCacheDependency封裝了SqlDependency,其行為與ASP.Net中其它的CacheDependency一樣。 SqlCacheDependency超越了SqlDependency,因為它可以工作在SQL Server 2005或者SQL Server早期版本上。當然對於SQL Server 2005之前的版本,它的實現是完全不同的。

如果您使用的是SQL Server早期版本,那麼SqlCacheDependency通過建立在被“監視”表上的觸發器進行工作。這些觸發器將變更信息記錄到另一張SQL Server表中,然後輪詢那張表。可以對啟用相依性功能的表以及輪詢的時間間隔進行配置。SQL Server 2005以前版本的實現細節已經超出了本文討論的范圍,更多信息請參閱Improved Caching in ASP.Net 2.0。

使用SQL Server 2005時,SqlCacheDependency封裝了一個與前面ADO.Net示例中類似的SqlDependency實例。以下是使用SqlCacheDependency的一個簡短示例:

// called from Page.Load
CreateSqlCacheDependency(SqlCommand cmd)
{
SqlCacheDependency dep = new SqlCacheDepedency(cmd);
Response.Cache.SetExpires(DateTime.Now.AddSeconds(60);
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(true);
Response.AddCacheDependency(dep);
}

一個很棒且易於使用的特性就是SqlCacheDependency可以和頁面緩存或者頁面片段緩存配合使用。您可以通過一個特殊的ASP.Net指示詞OutputCache聲明式地啟用所有SqlCommands的查詢通知功能。該方式為頁面中所有SqlCommand設置相同的SqlDependency。對於SQL Server 2005數據庫其聲明方式如下所示:

<%OutputCache SqlDependency="CommandNotification" ... %>

注意CommandNotification是關鍵字,其含義為“使用SQL Server 2005和SqlDependency”,如果使用早期的SQL Server版本,那麼該指示參數的語法是完全不同的。同樣,只有在特別的操作系統版本上運行ASP.Net 2.0時,才會啟用關鍵字CommandNotification設置的值。

熱心的通知

SQL Server查詢通知的設計策略是:頻繁通知用戶總比忘記通知用戶要好。盡管絕大多數情況您收到通知都是由於他人修改了表中的某一行致使緩存無效,但並非總是如此。例如,如果DBA回收了數據庫您會收到通知。如果查詢中引用的任何表被修改、刪除、或者清空,您也會收到通知。由於查詢通知回占用SQL Server資源,如果SQL Server受到資源不足的壓力,就可能從內部表中刪除查詢通知,這種情況下客戶端也會收到通知。由於每個通知請求都包含了一個超時值,如果訂閱超時也會通知您。

如果使用SqlDependency,那麼分發器會將所有信息封裝到一個SqlNotificationEventArgs實例中。該類包含了三個屬性:Info, Source和Type,這些屬性幫助您查明通知產生的原因。如果使用SqlNotificationRequest,那麼隊列消息的message_body字段包含的XML文檔中也含有相同的信息,但是您必須使用XPath或XQuery自己分析這些信息。此處是前面ADO.Net SqlNotificationRequest示例產生的XML文檔的例子:

<qn:QueryNotification
XMLns:qn="http://schemas.microsoft.com/SQL/Notifications/QueryNotification"
id="2" type="change" source="data" info="update"
database_id="6" user_id="1">
<qn:Message>{CFD53DDB-A633-4490-95A8-8E837D771707}</qn:Message>
</qn:QueryNotification>

注意:盡管通知的產生是由於將job_id = 5這一行的job_desc列值修改為“new job”,但在消息體中永遠無法看到這些信息。通知可以判斷出某個SQL語句修改了數據並因此導致您的結果集發生了變化,但是它還不夠聰明,無法分辨出UPDATE語句是否真正對數據進行了修改。例如,將某行的job_desc = "new job" 修改成 job_desc = "new job" 將導致通知的產生。同樣地,由於查詢通知是異步的並且是在您執行SQL命令或批時注冊的,因此可能您還沒讀取完結果集就收到了通知。如果您提交的查詢不符合規則,那麼也會立刻收到通知。這些規則就是前面我提到的關於索引視圖的規則。

何時不使用通知?一些勸誡

由於您現在已經了解了查詢通知的工作原理,因此可以很容易指出它們的用處:可改寫只讀表。每個通知都會占用SQL Server資源,因此在只讀表上使用通知將是浪費和不經濟的。此外也不要將通知用於即席查詢,因為那樣將導致大量不同的行集同時被“監視”。這裡有一個很有用的內部細節,即SQL Server會合並參數化查詢使用不同參數時占用的通知資源。始終使用參數化查詢(像上面SqlNotificationRequest示例中那樣)允許您利用這一特點並獲得增強的性能。如果您聽到這些勸言後有些擔心,那麼請記住性能問題並不意味著您無法收到恰當的通知。如果使用au_lname作為參數,user1監視au_lname為A-M的authors數據而user2監視au_lname為N-Z的數據,那麼每個用戶將只會接收到針對他們數據子集的“正確”的通知。

最後一點注意事項:當某些人談論通知應用程序時,他們想象著一間滿是股票經紀人的房間以及不斷變化的股票價格,每個顯示器都不停變化著。這樣使用查詢通知絕對是錯誤的,原因有兩個:

1.由於行集不斷變化,網絡將被大量的查詢通知和查詢刷新請求阻塞。

2.如果有相當多的用戶並且他們都“監視”相同的數據,那麼每個通知都將導致大量用戶同時重新查詢相同的行集。大量對相同數據集的查詢請求也可能導致SQL Server拒絕服務!

如果您覺得有些程序員會濫用該特性,那麼可以高興地告訴您Beta2以後版本中,SQL Server可以通過動態管理視圖為DBA提供更多監視該特性的信息。目前這些視圖只能顯示訂閱的信息。請記住這種可能性是始終存在的,即SQL Server 2005“判定”查詢通知占用了太多資源並開始清理它們。

結論

查詢通知是內置在SQL Server 2005中的一個強大新特性,可以直接在ADO.NET 2.0和ASP.NET 2.0中使用。盡管ADO.NET的特性(SqlNotificationRequest和SqlDependency)只能在SQL Server 2005數據庫上工作,但ASP.NET通過池的機制使得該特性“向後兼容”。請謹慎正確的使用該特性,牢記它的含義以及影響。對於該特性而言最好的“甜點”就是ASP.Net中那些可能被其他應用程序,當然也包括Web應用程序更新的可改寫只讀表。對於這種應用場景,查詢通知提供了程序員們盼望多年的解決方案。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved