快捷搜索:

剖析SQL Server 2005查询通知之基础篇(1)

择要 在本系列文章中,我们将深入探究若何把.NET 2.0和SQL Server 2005的查询看护特性联合起来,以便看护利用法度榜样何时关键数据发生变更进而达到打消反复查询数据库的目的。

一. 小序

数据库利用法度榜样的范例问题之一是更新迂腐的数据。

设想有一个范例的显示产品及其分类的电子商务网站。一个供应商的产品列表很可能并不常常发生变更,而其分类列表以致更不会频繁变动。然而,在用户每次浏览该网站时,必须从数据库中反复查询这些列表。这显然是一种范例的低效资本使用,开拓者和架构师都在绞尽脑汁设法主见子以削减这种挥霍。

缓冲技巧恰是“最小化”对这种险些“停滞”的数据进行重复查询的技巧之一。这种数据可以被进行一次性查询并存储在一个缓冲区中,而且利用法度榜样可以从缓存中重复地存取数据。有时环境下,才更新缓存以获得新数据。然则,环抱更新缓存的光阴调整方面呈现了几个问题。该多长光阴操作一次呢?例如,你每隔多长光阴盼望你的产品分类改变一次?每隔几个月一次?每隔两个月刷新一次该缓冲区若何?你知道会发生什么吗?就在你刷新缓存之后,分类被更新,而且鄙人一次刷新前在两个月的光阴里它将维持迂腐。

查询看护,是微软的ADO.NET和SQL Server小组协作开拓的新成果。简言之,查询看护容许你缓冲数据并且仅在SQL Server中的数据发生变更时才发出看护。一旦接到看护,你就可以刷新你的缓冲区或者采取你必要的任何步伐。

在SQL Server 2005中引入的一种新特性“Service Broker”使得查询看护成为可能。Service Broker把行列步队机制引入到数据库治理中,它应用一组行列步队与办事进行通讯,而办事反过来也知道若何往回通讯以调用响应的实体。着实,这些行列步队和办事都是一些与表、视图和存储历程一样的类工具。只管完全可以在SQL Server内应用Service Broker,然则ADO.NET知道若何与Service Broker进行通讯以触发这种机制并且从Service Broker中检索回看护。

留意 当SQL Server中的数据发生改变时,查询看护容许你缓冲数据并且看护你。

在.NET一端,存在很多种“钩入”这种功能的要领。ADO.NET 2.0供给了System.Data.SqlClient.SqlDependency和System.Data.Sql.SqlNotificationRequest类。SqlDependency是SqlNotificationRequest的一种高档实现,并且是当应用ADO.NET 2.0时你最有可能应用的类。ASP.NET 2.0也经由过程System.Web.Caching.SqlCache-Dependency类(它供给了一个针对SqlDependency的包装器)与Service Broker进行通讯,而且这是直接经由过程在一个ASP.NET页面中应用指令以声明要领供给的功能实现的。这容许ASP.NET开拓者轻易地实现使依附于SQL Server中的数据中的缓存无效。

二. .NET与Service Broker的通讯

上面这些技巧是若何联合到一路来办理“缓冲之谜”的呢?只管你可以采取很多的步伐以容许SQL Server把办事供给给.NET;然则,关键还在于,发送到SQL Server的查询具有一个依赖到它们的标志以便奉告SQL Server,除了返回结果集外,SQL Server还应该把该查询(及其哀求者)注册到Service Broker。为此,你要创建一个感知该查询的行列步队和一个依赖到该行列步队的办事,并且知道若何返回到客户端。假如该结果集中的任何一行在数据库中获得更新,那么在相关行列步队中的项将触发,并且反过来,把一条消息发送到它的办事,然后把一个看护发送回初始化该哀求的利用法度榜样。

图1是SQL Server Management Studio的一个快照,它显示了在数据库的Service Broker部分中的行列步队(Queues)和办事(Services)。

留意:对付客户端利用法度榜样来说,应该限定你的查询看护应用—不多于十个并发用户。

对付较小规模的环境而言,下拉式列表框是另一种范例的数据集;此时该数据集更新的次数并不如哀求的次数多。产品列表、州列表、国家列表、供应商、贩卖人,以致更多不太必要频繁改变的信息恰是应用看护的较好候选。

四. 为应用查询看护作筹备

由于默认环境下SQL Server 2005处于高度安然的状态,以是你必要“打开”一些功能才能应用查询看护。首先,你要应用的每一个数据库都必要启动Service Broker功能。为此,你可以在T-SQL中应用如下敕令实现:

USE mydatabase

ALTER DATABASE mydb SET ENABLE_BROKER

别的,你必要赋予一些SQL Server权限以容许非治理员帐户能够介入应用查询看护。

五. SqlDependency.Start和Stop

SqlDependency和SqlCacheDependency都要求,在任何看护哀求前先调用静态措施SqlDependency.Start()。这个措施认真创建一个SqlConnection以实现在数据改变时接管看护。留意,你仅必要在一个利用法度榜样的生命周期的开始建立这些内容。例如,在一个ASP.NET利用法度榜样中,global.asax文件的Application_Start事故处置惩罚器便是实现这一功能的好地方。

留意,对包孕在看护中的每一个连接都应该调用Start措施。是以,假如你在利用法度榜样中存取多个数据库,那么你必要为每一个数据库调用Start。鄙人列示例中,有一个针对Pubs数据库的连接串pubsConn,它在这个利用法度榜样的web.config文件中定义。

为了堵截这个连接,你可以应用SqlDependency.Stop(),这也是一个静态措施。

Sub Application_Start(ByVal sender as Object, _

ByVal e as EventArgs)

System.Data.SqlClient.SqlDependency.Start _

(System.Configuration.ConfigurationManager. _

Connectionstrings("pubsConn").ConnectionString)

End Sub

Sub Application_End(ByVal sender as Object,

ByVal e as EventArgs)

System.Data.SqlClient.SqlDependency.Stop _

(System.Configuration.ConfigurationManager. _

Connectionstrings("pubsConn").ConnectionString)

End Sub

假如你在调用Start和Stop的同时察看SQL Server Profiler,那么你会看到许多有趣的信息。当调用Start时,利用法度榜样运行一个查询以确保支持Service Broker,然后创建一个存储历程备今后用于清除在Service Broker根基布局中的SqlDependency行列步队和办事。着末,它运行一个SQL Server 2005 WaitFor敕令,该敕令认真查询在Notification Service部分的进口。这便是假如你应用ADO.NET的初级SqlNotificationRequest工具的话所有你必要显式完成的工作。

Imports System.Data.SqlClient

Public Class NotificationTest

Dim dep As SqlDependency

Public Function DepTest() As SqlDataReader

Dim conn As New SqlConnection(connstring)

conn.Open()

Dim cmd As New SqlCommand( _

"SELECT au_id, au_lname,au_fname " & _

"FROM dbo.authors", conn)

dep = New SqlDependency(cmd)

Dim rdr As SqlDataReader

rdr = cmd.ExecuteReader()

Return rdr

End Function

End Class

现在,你已经注册了依附性,然则当看护返回到利用法度榜样时你还根本没有捕获它。不过,SqlDependency类供给了两种要领来懂得一个看护。一种要领是经由过程OnChange事故,你可以经由过程创建一个代理来捕获它;另一种要领是经由过程属性HasChanges,你可以在你的利用法度榜样逻辑中对之进行测试。鄙人列代码中,我在OnDepChange事故中添加了代码以便在后面的某个时刻测试看护。

Imports System.Data.SqlClient

Public Class NotificationTest

Dim dep As SqlDependency

Public Function DepTest() As SqlDataReader

Dim conn As New SqlConnection(connstring)

conn.Open()

Dim cmd As New SqlCommand( _

"SELECT au_id,au_lname,au_fname FROM " + _

"dbo.authors", conn)

dep = New SqlDependency(cmd)

AddHandler dep.OnChange, AddressOf OnDepChange

Dim rdr As SqlDataReader

rdr = cmd.ExecuteReader()

Return rdr

End Function'处置惩罚器措施

Public Sub OnDepChange(ByVal sender As Object, _

ByVal e As SqlNotificationEventArgs)

Dim DepInfo As String = e.Info.ToString

'做一些工作以相应看护

End Sub

Public ReadOnly Property HasChanges() As Boolean

Get

Return dep.HasChanges

End Get

End Property

End Class

现在,我们来看一下其事情道理。首先,把一个断点放到OnDepChange事故的End Sub代码行。然后,从你爱好的网页、表单法度榜样或节制台法度榜样中调用DepTest函数来进行测试。在返回SqlDataReader后,在Visual Studio 2005的Server Explorer或在SQL Server Management Studio中打开Authors表并且编辑某一个字段内容。例如,一旦锁定这一改变,那么,当你把光标移 动到表中的一个新行时,断点应该被激活。

七. SQLNotificationEventArgs

当你看到看护切实着实从数据库中传来时,你可以阐发一下响应变量的值,它是一个SqlNotificationEventArgs工具。SqlDependency老是跟着OnChange事故返回这个工具,而且它是很有用的。此中,SqlNotificationInfo是一个具有18种可能值的罗列类型。此中,一些值对应环境正常,而另一些显示出了问题。这些罗列中有Update,Insert和Delete—奉告你在数据中发生了什么类型的变更。还有其它一些值纵然在事故发生时也不会被发送。例如,从新启动办事器将引发所有的看护;而罗列值Drop或Truncate奉告你已经对依附的表实现了某种操作。

别的,还存在一些依附性以致还不能被注册的情形,例如假如你试图对一个UPDATE查询设置一个依附性将返回Invalid。而返回值Query显示你的查询语法并不相符看护的严格规则。上面罗列表中的着末两个罗列值,还有其它几个与不能注册查询相关的罗列值在履行该敕令时被急速返回。

经由过程查找MSDN库中的有关SqlNotificationInfo罗列文档,你可以获得这些罗列的完全列表。

当我一些场合上讨论查询看护时,人们老是问我:“看护是否会奉告你发生了什么工作?”。回答是“不会”。

总之,SQLNotificationEventArgs能够向你给出一个看护中最为具体的信息,而这些信息在调试排错时是异常有用的。

您可能还会对下面的文章感兴趣: