网页的设计本来就非常重视缓存(cache)的机制,因此在 ASP.NET 1.0/1.1 时就已经对高速缓存多有着墨。而在 ASP.NET 2.0 中除了网页架构外,更是大幅增强服务器控制高速缓存的能力。对于 SQL Server 2000/7.0 以往的版本也提供了通过对数据表加上额外的触发器(Trigger)和数据表来记录变化,让目标数据有变化时可以通过轮询(Poll)该辅助的数据表来触发缓存失效的过程。但关于 ASP.NET 2.0 的讨论超过了本书的范围,你可以到微软网站或是 .NET Magazine(http://www.netmag.com.tw) 找寻相关的信息。
针对 SQL Server 2005,在 ASP.NET 2.0 内则可以直接通过 SqlCacheDependency 类与前述的主动通知机制协作,当 DB 内的数据有变化时,让高速缓存的数据立刻失效,重新回到 SQL Server 取得最新的数据后更新缓存内容。而 SqlCacheDependenc类就是包装前述的 SqlDependenc 类,让 ASP.NET 的高速缓存失效,除了文件变化外,也能够通过数据库内容的变化自动触发更新。
我们提供的程序范例画面如图12-11 所示:
图12-11 通过 ASP.NET 2.0 提供的 SqlCacheDependency 类在
SQL 数据库内相关纪录更新时,自动让缓存失效
整个网页的程序代码范例如列表12-10:
程序代码列表12-10 ASP.NET 的 Cache 可以因为存放在数据库内的数据改变而自动失效
Private Sub myBind()
'不管是通过按钮回来,还是以 GridView 的分页事件回来,都可以通过此方法更新数据
If Me.Cache("Product") Is Nothing Then
UpdateCache()
End If
GridView1.DataSource = CType(Me.Cache("Product"), DataSet).Tables(0)
GridView1.DataBind()
End Sub
Private Sub UpdateCache()
Dim cnn As New SqlConnection("Data Source=.;Initial Catalog=AdventureWorks;” & _
“Persist Security Info=True;User ID=sa;Password=password")
Dim adp As New SqlDataAdapter( _
"SELECT ProductID, Name, ListPrice FROM Production.Product", cnn)
'通过新的 SqlCacheDependency 让 SQL Server 内的数据改变后,Cache 自动过期失效
Dim dep As New SqlCacheDependency(adp.SelectCommand)
Dim ds As New DataSet
adp.Fill(ds)
'加入对 SqlCacheDependency 的 Cache 机制
Me.Cache.Add("Product", ds, dep, Caching.Cache.NoAbsoluteExpiration, _
Caching.Cache.NoSlidingExpiration, CacheItemPriority.Default, _
New CacheItemRemovedCallback(AddressOf DataDiff))
'若 Cache 中已经有相同键值的对象,则直接覆盖该对象,若用 Add ,
'若已经存在该对象,就会触发错误
Me.Cache.Insert("LastUpdate", DateTime.Now)
End Sub
Private Sub DataDiff(ByVal key As String, ByVal value As Object, _
ByVal reason As CacheItemRemovedReason)
'Cache 失效后自动调用的 delegation 函数
UpdateCache()
End Sub
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Button1.Click
If Not Me.Cache("Product") Is Nothing Then
SqlDependency.Stop("Data Source=.;Initial Catalog=AdventureWorks;User ID=sa;Password=password")
SqlDependency.Start("Data Source=.;Initial Catalog=AdventureWorks;User ID=sa;Password=password")
Me.Cache.Remove("Product")
End If
End Sub
Function GetUpdateTime() As String
'GridView 通过 Caption='<%#GetUpdateTime()%>' 属性所做的数据绑定
'就直接调用这个函数,因为 GridView 会通过前端的 Script 只做内容的
'Post Back,而不是全网页刷新,所以若通过其他的对象如 Label 来
'显示最后更新的时间,则在用户通过选择不同分页回来更新数据时,
'数据自身会更新,但在网页其他地方以 Label 控制项显示的更新时间不会变化
'因此直接一起在 GridView 内显示
Dim strRet As String = ""
If Me.Cache("LastUpdate") Is Nothing Then
strRet = "没有高速缓存数据"
Else
strRet = "服务器端高速缓存(Cache)最后更新时间:" & _
CType(Me.Cache("LastUpdate"), DateTime).ToString()
End If
Return strRet
End Function
Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, _
ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) _
Handles GridView1.PageIndexChanging
GridView1.PageIndex = e.NewPageIndex
myBind()
End Sub
而在 Global.asax 的文件内,我们加了以下两段程序代码:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
SqlDependency.Start("Data Source=.;Initial Catalog=AdventureWorks;Persist Security Info=True;User ID=sa;Password=password")
End Sub
Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
SqlDependency.Stop("Data Source=.;Initial Catalog=AdventureWorks;Persist Security Info=True;User ID=sa;Password=password")
End Sub
责任编辑:cyth