日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

浅析SQL Server 2005中的主动式通知机制

發(fā)布時(shí)間:2023/12/10 数据库 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅析SQL Server 2005中的主动式通知机制 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、引言

在開發(fā)多人同時(shí)訪問的Web應(yīng)用程序(其實(shí)不只這類程序)時(shí),開發(fā)人員往往會(huì)在緩存策略的設(shè)計(jì)上狠下功夫。這是因?yàn)?#xff0c;如果將這種環(huán)境下不常變更的數(shù)據(jù)臨時(shí)存放在應(yīng)用程序服務(wù)器或是用戶機(jī)器上的話,可以避免頻繁地往返訪問數(shù)據(jù)庫—而數(shù)據(jù)庫訪問是要符出昂貴代價(jià)的。以往在低版本的SQL Server(SQL Server 2000及以前版本)中,當(dāng)需要提供數(shù)據(jù)庫內(nèi)他人更新后的狀況時(shí),主要是通過輪詢數(shù)據(jù)庫機(jī)制來提供對(duì)數(shù)據(jù)庫的不斷查詢;也可能是借助于存儲(chǔ)于數(shù)據(jù)庫表格中的觸發(fā)器或者通過消息隊(duì)列方式來達(dá)到通知目的。如今,作為微軟.NET 2.0戰(zhàn)略的重要組成部分之一的SQL Server 2005首次引入了主動(dòng)式通知(Query Notification)機(jī)制。SQL Server 2005在所使用數(shù)據(jù)更改時(shí),會(huì)主動(dòng)地通知你。這種新的設(shè)計(jì)模式會(huì)讓你在系統(tǒng)數(shù)據(jù)未更新時(shí),減輕浪費(fèi)網(wǎng)絡(luò)來回輪詢的負(fù)擔(dān),從而有可能極大地提高系統(tǒng)性能。

本文中,我想通過一個(gè)簡單的Windows桌面表單示例(基于SQL Server 2005的范例數(shù)據(jù)庫AdventureWorks)向讀者展示SQL Server 2005中這種新的主動(dòng)地通知工作機(jī)理。

【另注】由于Visual Studio 2005的革命性變化,你可以極為容易地把這個(gè)例子更改到Web應(yīng)用程序場(chǎng)合下。

二、SQL Server 2005中的主動(dòng)式通知

主動(dòng)式通知(也稱為“查詢通知”),是微軟ADO.NET和SQL Server小組協(xié)作開發(fā)的新成果。它允許你對(duì)數(shù)據(jù)進(jìn)行緩沖并且僅在SQL Server中的數(shù)據(jù)發(fā)生變化時(shí)才發(fā)出通知;一旦接到通知,你就可以刷新相應(yīng)的緩沖區(qū)或者采取其它必要的措施。

在SQL Server 2005中引入的一種新特征“Service Broker”使得查詢通知成為可能。Service Broker把隊(duì)列機(jī)制引入到數(shù)據(jù)庫管理中,它使用一組隊(duì)列與服務(wù)進(jìn)行通訊,而服務(wù)反過來也知道如何往回通訊以調(diào)用相應(yīng)的實(shí)體。其實(shí),這些隊(duì)列和服務(wù)都是一些與表、視圖和存儲(chǔ)過程一樣的類對(duì)象。盡管完全可以在SQL Server內(nèi)使用Service Broker,但是ADO.NET也知道如何與Service Broker進(jìn)行通訊以觸發(fā)這種機(jī)制并且從Service Broker中檢索回通知。

【作者注】Service Broker是SQL Server 2005中新增加的一項(xiàng)重要服務(wù),旨在為日趨流行的面向服務(wù)的架構(gòu)(Service-Oriented Architecture,即“SOA”)在數(shù)據(jù)庫存儲(chǔ)級(jí)提供基礎(chǔ)性支持。

其實(shí),完整的通知架構(gòu)還是比較復(fù)雜的。其中參與的組件可能包括:SQL Server 2005查詢引擎、Service Broker、系統(tǒng)存儲(chǔ)過程sp_DispatcherProc;ADO.NET的SqlNotification類(System.Data.Sql.SqlNotificationRequest)、SqlDependency類(System.Data.Sql.SqlDependency);以及ASP.NET 2.0中新的Cache類(System.Web.Caching.Cache)等等。

下圖1展示了SQL Server 2005中的主動(dòng)通知機(jī)制及其與客戶端ASP.NET頁面交互的示意圖。

?

圖1:SQL Server 2005主動(dòng)通知機(jī)制示意圖

上面的運(yùn)行邏輯大致如下:

(1)SqlCommand類中提供了一個(gè)Notification屬性,用于存儲(chǔ)通知相關(guān)的設(shè)置。當(dāng)SqlCommand執(zhí)行時(shí),會(huì)讓傳遞該執(zhí)行需求的TDS協(xié)議附加上通知的相應(yīng)信息。
(2)SQL Server 2005收到該需求后,為這個(gè)需求注冊(cè)通知,并執(zhí)行該需求自身的SQL語句;
(3)接下來,SQL Server 2005會(huì)監(jiān)控后續(xù)執(zhí)行的DML語法,并確定是否能夠影響前一步返回給前端的數(shù)據(jù)集;一旦有影響,則會(huì)立即發(fā)送一個(gè)消息到Service Broker;
(4)Service Broker的隊(duì)列中有消息后,可能發(fā)生如下情況:
? a)Notification在前端應(yīng)用程序偵聽的隊(duì)列中放入消息,由ADO.NET的下層自動(dòng)讀取消息并觸發(fā)事件;
? b)在Service Broker內(nèi)的消息持續(xù)保留著,較高級(jí)的前端應(yīng)用程序會(huì)自己處理這個(gè)消息。

#p#

如前所述,由于SQL Server 2005的通知機(jī)制在基層上依賴于Services Broker,所以要發(fā)出通知的數(shù)據(jù)庫必須讓Services Broker啟動(dòng)。Services Broker利用SQL Server 2005所提供的隊(duì)列創(chuàng)建異步通知。而通知其實(shí)就是一組Services Broker內(nèi)置好的服務(wù)(也即是標(biāo)準(zhǔn)的消息、發(fā)送的消息及發(fā)送消息的規(guī)則等等)。下圖2中,我們通過SQL Server Management Studio中的對(duì)象資源管理器窗口查看每一個(gè)范例數(shù)據(jù)庫AdventureWorks的“Services Broker”節(jié)點(diǎn)下屬相關(guān)的設(shè)置情況:

?

圖2:SQL Server 2005在Services Broker中已經(jīng)準(zhǔn)備好主動(dòng)式通知設(shè)置情況

前面已經(jīng)提到,我們想通過SQL Server 2005的范例數(shù)據(jù)庫AdventureWorks進(jìn)行試驗(yàn);所以,若要讓程序能夠收到通知,必須先啟動(dòng)該數(shù)據(jù)庫的相應(yīng)服務(wù),同時(shí)還要允許登錄的帳戶訂閱這種查詢通知。下面SQL語句實(shí)現(xiàn)創(chuàng)建相應(yīng)的設(shè)置:

--啟動(dòng)Service Broker服務(wù)支持

ALTER DATABASE AdventureWorks SET ENABLE_BROKER
--
--【提示】我們無法直接在sp_dboption中(使用“EXEC sp_dboption AdventureWorks”語句)
--看出某個(gè)數(shù)據(jù)庫是否啟動(dòng)了Service Broker服務(wù)
--需要觀察sys.databases的is_broker_enabled字段才知道是否已經(jīng)啟動(dòng)—使用如下語句:

SELECT * FROM sys.databases

--允許某個(gè)賬號(hào)訂閱查詢
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO [YourComputerName\UserName]

三、示例分析

有了上面的分析和相應(yīng)的SQL設(shè)置后,現(xiàn)在讓我們來觀察一個(gè)使用SQL Server 2005主動(dòng)式通知機(jī)制的Windows桌面應(yīng)用程序的示例。程序相應(yīng)表單的設(shè)計(jì)界面如下圖3所示:

?

圖3:表單的設(shè)計(jì)界面

Public Class DeskNotification

??? Dim conn As New SqlConnection(ADONET20.My.Settings.AdventureWorksConnection)
??? Delegate Sub PopulateList()
??? Private Sub DeskNotification_Load(ByVal sender As System.Object, ByVal e As

System.EventArgs) Handles MyBase.Load
??????? SqlDependency.Start(ADONET20.My.Settings.AdventureWorksConnection)
??????? ‘取得初始數(shù)據(jù)
??????? ListProducts()
??? End Sub

??? Private Sub productListBox_SelectedIndexChanged(ByVal sender As System.Object,

ByVal e As System.EventArgs) Handles productListBox.SelectedIndexChanged
??????? Dim strItem As String = productListBox.SelectedItem.ToString
??????? lblId.Text = strItem.Substring(0, strItem.IndexOf("-") - 1)
??????? txtPrice.Text = strItem.Substring(strItem.IndexOf(":") + 1)
??? End Sub

??? Private Sub btnUpdate_Click(ByVal sender As System.Object,

ByVal e As System.EventArgs) Handles btnUpdate.Click
??????? Dim cnn As New SqlConnection(ADONET20.My.Settings.AdventureWorksConnection)
??????? If lblId.Text = "無" Then
??????????? MessageBox.Show("請(qǐng)選擇某一條記錄")
??????????? Exit Sub
??????? End If
??????? cnn.Open()
??????? Dim cmd As New SqlCommand( _
??????? "UPDATE Production.Product SET ListPrice=" & txtPrice.Text & " WHERE

ProductID=" & lblId.Text, _
??????? cnn)
??????? cmd.ExecuteNonQuery()
??????? cnn.Close()

??? End Sub
??? Sub OnDependencyChanged(ByVal sender As Object, ByVal e As SqlNotificationEventArgs)
??????? 'SqlDependency對(duì)象的OnChanged事件觸發(fā)時(shí)
??????? '要執(zhí)行的業(yè)務(wù)邏輯
??????? Dim dR As DialogResult
??????? dR = MessageBox.Show("數(shù)據(jù)已經(jīng)完畢,要更新數(shù)據(jù)嗎?", e.Info.ToString, _
??????? MessageBoxButtons.YesNo, MessageBoxIcon.Question)
??????? If dR = Windows.Forms.DialogResult.Yes Then
??????????? '由表單的主線程實(shí)現(xiàn)數(shù)據(jù)更新
??????????? Try
??????????????? Me.Invoke(New PopulateList(AddressOf ListProducts))
??????????? Catch ex As Exception
??????????????? MessageBox.Show(ex.Message)
??????????? End Try
??????? End If
??? End Sub

??? Public Sub ListProducts()
??????? '重新裝載數(shù)據(jù)
??????? ' SqlDependency設(shè)置后,僅會(huì)注冊(cè)一次的事件通知
??????? Dim dep As New SqlDependency()
??????? '設(shè)置SqlDependency對(duì)象的OnChanged事件發(fā)生時(shí)要調(diào)用哪個(gè)事件處理器
??????? AddHandler dep.OnChange, AddressOf OnDependencyChanged
??????? '限制查詢的范圍,避免太大的范圍的大量用戶都影響到這個(gè)范圍內(nèi)的數(shù)據(jù)以致使SQL Server
??????? '頻繁地觸發(fā)通知
??????? Using cmd As New SqlCommand( _
??????? "SELECT ProductID, Name, ListPrice FROM Production.Product " & _
??????? "WHERE ProductID BETWEEN @Start AND @End", conn)
??????????? With cmd
??????????????? .Parameters.Add(New SqlParameter("@Start", Data.SqlDbType.Int))
??????????????? .Parameters.Add(New SqlParameter("@End", Data.SqlDbType.Int))
??????????????? .Parameters(0).Value = txtStart.Text
??????????????? .Parameters(1).Value = txtEnd.Text
??????????? End With

??????????? '自動(dòng)幫助我們?cè)O(shè)置SqlCommand的Notification屬性所需的SqlNotificationRequest對(duì)象
??????????? '可以通過Debug來觀察SqlCommand對(duì)象執(zhí)行前后的關(guān)系
??????????? dep.AddCommandDependency(cmd)
??????????? productListBox.Items.Clear()
??????????? conn.Open()
??????????? Dim reader As SqlDataReader = cmd.ExecuteReader()
??????????? While reader.Read()
??????????????? productListBox.Items.Add(reader("ProductID") & " - " & _
??????????????? reader("Name").ToString & ": " & reader("ListPrice").ToString)
??????????? End While
??????? End Using
??????? conn.Close()
??? End Sub

??? Private Sub DeskNotification_FormClosing(ByVal sender As System.Object,

ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
??????? SqlDependency.Stop(ADONET20.My.Settings.AdventureWorksConnection)

??? End Sub
End Class

#p#

在這個(gè)例子中,我們首先在Global.asax文件內(nèi)的Application_Start事件加入通過SqlDependency類的靜態(tài)方法Start啟動(dòng)監(jiān)聽。注意,這個(gè)Start方法需要傳遞數(shù)據(jù)庫連接字符串。它將完成如下相應(yīng)操作:

◆打開一條新的不經(jīng)過數(shù)據(jù)庫連接池的到SQL Server 2005的連接;
◆在服務(wù)器上創(chuàng)建一個(gè)新的隊(duì)列,并賦予唯一名稱;
◆在該隊(duì)列上創(chuàng)建一個(gè)唯一名稱的服務(wù);
◆在服務(wù)器上創(chuàng)建一個(gè)新的存儲(chǔ)過程,在客戶端不再監(jiān)聽隊(duì)列時(shí),清除掉上述的臨時(shí)創(chuàng)建的各種對(duì)象;
◆偵聽隊(duì)列所收到的更改通知。

【注意】在上面的例子中,盡管你可以通過SqlCommand實(shí)例中的SQL更改記錄,但并沒有自動(dòng)更新列表框內(nèi)的記錄數(shù)據(jù),而是在收到SQL Server記錄改變的通知后,通過事件觸發(fā)指到OnDenpedencyChanged函數(shù)調(diào)用主線程重新執(zhí)行ListProducts方法,從相關(guān)數(shù)據(jù)表讀取更新后的記錄來重設(shè)列表框的內(nèi)容。

四、何時(shí)使用主動(dòng)式通知機(jī)制

查詢通知是針對(duì)于并不經(jīng)常改變的數(shù)據(jù)而設(shè)計(jì)的。最好把它應(yīng)用于服務(wù)器端的應(yīng)用程序(例如ASP.NET或remoting)而不是客戶端應(yīng)用程序(例如Windows表單應(yīng)用程序)。記住,每一個(gè)通知請(qǐng)求都要在SQL Server中注冊(cè)。如果你擁有大量的都有通知請(qǐng)求的客戶端應(yīng)用程序,那么這可能會(huì)導(dǎo)致你的服務(wù)器產(chǎn)生資源問題。鑒于此,微軟推薦,對(duì)于客戶端應(yīng)用程序,你應(yīng)該限制使用查詢通知的最大并行用戶數(shù)不多于十個(gè)。

對(duì)于大規(guī)模應(yīng)用程序來說,查詢通知可能是一種強(qiáng)有力的幫助,而不用簡單地添加越來越多的服務(wù)器以滿足要求。設(shè)想,有一家大型的為成千上百萬用戶提供在線軟件更新服務(wù)的軟件公司。不是使每一個(gè)用戶的更新操作都觸發(fā)服務(wù)器上的另一個(gè)查詢來確定需要哪些組件,而是能夠緩沖查詢結(jié)果并且可以直接從該緩存中服務(wù)匹配的查詢。

對(duì)于較小規(guī)模的情況而言,下拉式列表框是另一種典型的數(shù)據(jù)集;此時(shí)該數(shù)據(jù)集更新的次數(shù)一般不如請(qǐng)求的次數(shù)多。產(chǎn)品列表、州列表、國家列表、供應(yīng)商、銷售人,甚至更多不太需要頻繁改變的信息正是使用上述通知機(jī)制的較好候選。

五、小結(jié)

盡管查詢通知是.NET 2.0中最重要的特征之一,但是目前它仍然難與其它優(yōu)秀特征(例如ASP.NET中的泛型或UI魔術(shù)等)相銜接。然而,無論你使用它來防止針對(duì)于含有數(shù)百個(gè)項(xiàng)的下拉列表框的連續(xù)的反復(fù)查詢,還是使用它來管理基于Web的上百萬的客戶端計(jì)算機(jī)的更新,它都能有效地幫助你減少資源開支。就其最簡單的應(yīng)用來看,借助于ASP.NET OutputCache指令(或通過在你的Web應(yīng)用程序的中間層或Web服務(wù)中構(gòu)建一種復(fù)雜緩沖的機(jī)制),查詢通知可以成為創(chuàng)建可擴(kuò)展的具有響應(yīng)性的應(yīng)用程序的強(qiáng)有力的協(xié)作開發(fā)工具。

【另注】本文基于SQL Server 2005 Express Edition調(diào)試通過。另外,盡管查詢通知可以與SQL Server Express(SSE)一起使用,但是SSE數(shù)據(jù)庫必須是一個(gè)命名的實(shí)例(命名的實(shí)例是安裝選項(xiàng)之一)。

轉(zhuǎn)載于:https://www.cnblogs.com/amylis_chen/p/3234594.html

總結(jié)

以上是生活随笔為你收集整理的浅析SQL Server 2005中的主动式通知机制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。