作者:G. Andrew Duthie
Graymad Enterprises, Inc.
2004 年 2 月
適用於:
Microsoft® ASP.NET
摘要:瞭解 ASP.NET Whidbey 所提供的快取新功能 — ASP.NET 應用程式開發人員可以利用這些功能,大幅提昇新一代 ASP.NET 應用程式的效能。(列印共 23 頁)
目錄
簡介
快取相依性的擴充性
SQL 快取失效
快取後置替換
結論
相關著作
簡介
ASP.NET 最有力且最實用 (卻也是最常被忽略) 的功能之一,就是對於網頁輸出與任意資料這兩者廣泛的快取支援。ASP.NET 可讓您儲存記憶體中呈現的網頁輸出、使用者控制項輸出,以及任何從集合到資料集的輸出。ASP.NET 也提供決定快取更新時機的各種技巧,從簡單的以時間為基礎的快取到期,到以索引鍵和檔案為基礎的快取相依性。
使用過 ASP.NET 目前版本快取功能的人都知道它能顯著提升效能與可調整性。由於您是從記憶體處理內容 (而非從資料庫和/或重新處理的網頁),因此可提升效能;由於處理器和檔案系統 (和/或資料庫) 不再需要處理每次的網頁要求,因此可提升可調整性。
但是 ASP.NET 團隊並不滿意在 ASP.NET 中的快取現況,因此打算在 ASP.NET Whidbey 中推出若干新的快取功能,本文將就這些新功能加以說明。我會將討論重點放在下列三項功能:
- 可擴充的快取相依性
- SQL 快取失效
- 快取後置替換
快取相依性的擴充性
在 ASP.NET 1.1 中,您可以使用相依性使快取項目自動到期,但這項功能卻有其侷限。您可以使用檔案和其他快取索引鍵當作相依性項目,但用途就僅止於此。這雖然實用,但相信很多人早就渴望能夠自行擴充相依性機制。現在終於可以如願以償,這要歸功於這次加入新版本的 CacheDependency 類別不再是密封 (Sealed) 類別 (表示您現在可以繼承此類別)。此類別的新版本會公開三個新成員,以供開發人員使用:
- GetUniqueID — 覆寫後,可讓您將自訂快取相依性的唯一識別項傳回給呼叫者。
- DependencyDispose — 用於處置由自訂快取相依性類別所使用的資源。當您建立自訂快取相依性時,必須實作此方法。
- NotifyDependencyChanged — 呼叫後,可使依賴自訂快取相依性執行個體的快取項目到期。
我們將在下列範例中使用後面兩個成員。在範例中,我會示範如何建立自訂的快取相依性以及如何快取 XmlDocument 的結果,這個自訂的快取相依性將會從 Blog 或其他新聞來源讀取 RSS (Really Simple Syndication) 餵送。接著會使用 XMLDocument 與 ASP.NET Xml 控制項來顯示 Blog 的內容 (使用 XSL 樣式表將其轉換成 HTML)。
若要建立自己的自訂快取相依性,第一步是建立繼承 CacheDependency 類別的新類別。為了避免使用完整名稱來建立新類別,您需要匯入 System.Web.Caching 命名空間。
注意 我們還會匯入 System.Threading 和 System.Xml 以方便存取其 Timer 類別和 XmlDocument 類別。
類別定義看起來如下:
Imports System Imports System.Web Imports System.Threading Imports System.Web.Caching Imports System.Xml Namespace v2_Caching Public Class BlogCacheDependency Inherits CacheDependency 'class code here End Namespace
接下來我們要加入一些成員變數:
' Timer is used to do dependency checks on a separate thread Shared TickTock As Timer Dim m_PollTimeSec As Integer = 300 Dim m_RSS As XmlDocument Dim m_Feed As String
Timer 類別是用來輪詢 RSS 餵送,以尋找變更內容。其他變數分別是輪詢時間、包含初始 RSS 的 XmlDocument,以及 RSS 餵送的 URL。
為了能夠顯示 XmlDocument,我們會加入公用屬性:
Public ReadOnly Property RSS() As XmlDocument Get Return m_RSS End Get End Property
請注意,因為我們只要將 RSS 傳回用戶端,因此會將此屬性標記為 ReadOnly,而且不包含 Set 存取子。
接著,我們會介紹 BlogCacheDependency 類別的兩個關鍵項目:建構函式與 CheckDependencyCallback 方法。建構函式如下所示:
' BlogCacheDependency Constructor Public Sub New(ByVal Feed As String, ByVal PollTimeSec As Integer) m_Feed = Feed m_PollTimeSec = PollTimeSec m_RSS = GetRSS(m_Feed) If TickTock Is Nothing Then TickTock = New Timer(New _ TimerCallback(AddressOf CheckDependencyCallback), Me, _ (m_PollTimeSec * 1000), (m_PollTimeSec * 1000)) End If End Sub
建構函式接收的字串中包含 RSS 餵送要擷取和檢查的 URL,它還會接收一個整數,其中包含餵送的每次輪詢要求之間的秒數。這些值會儲存在區域成員變數中,然後藉由呼叫 GetRSS 方法來填入 m_RSS 成員變數,這待會兒就會加以說明。最後,建構函式會查看 Timer 成員變數是否已經執行個體化,如果沒有,便會建立新的計時器執行個體,並根據 m_PollTimeSec 成員變數的值,將之設為定期呼叫 CheckDependencyCallback 方法。
CheckDependencyCallback (如下所示) 會建立型別 BlogCacheDependency (由 Sender 引數指派給 CheckDependencyCallback) 的區域執行個體變數,然後從 GetRSS 方法提取並建立新的 XmlDocument,再比較其 OuterXml 的值與 m_RSS 成員變數 (其中包含在建構涵式中取得的原始 XmlDocument) 的值)。如果比較結果相同,則不會採取任何動作。但如果比較結果不同,程式碼會呼叫 NotifyDependencyChanged 以通知 ASP.NET 快取引擎移除已快取的項目。
Public Sub CheckDependencyCallback(ByVal Sender As Object) Dim BCD As BlogCacheDependency = Sender Dim NewRSS As XmlDocument = GetRSS(m_Feed) If Not NewRSS.OuterXml = m_RSS.OuterXml Then BCD.NotifyDependencyChanged(BCD, EventArgs.Empty) End If End Sub
GetRSS 方法非常簡單:
Function GetRSS(ByVal Feed As String) As XmlDocument Dim RSSDoc As New XmlDocument RSSDoc.Load(m_Feed) Return RSSDoc End Function
這個方法很單純,主要是建立型別 XmlDocument 的區域變數,呼叫 XmlDocument 的 Load 方法,將 m_Feed 變數包含的 URL 傳遞給它,再將 XmlDocument 傳回給呼叫者。您會發現要擷取 RSS 餵送十分容易。因為 RSS 是 XML,因此只需要少數幾行程式碼就能夠取得 RSS 餵送。稍後您會看見,將 RSS 餵送格式化為使用 XSL 來顯示有多麼簡單。
最後,在處置我們自訂的依存性類別時,我們必須進行一些清理作業。我們將採取覆寫 DependencyDispose 方法的方式,並於其中處置我們的 Timer 執行個體:
Protected Overrides Sub DependencyDispose() TickTock = Nothing MyBase.DependencyDispose() End Sub
這麼一來,就交代完自訂快取相依性類別的程式碼 — 總共才不到 50 行程式碼!多虧有 Whidbey 的程式碼編譯新功能,只要將類別儲存到網站的 Code 資料夾中,ASP.NET 便會為您自動編譯類別。
自訂快取相依性的使用甚至更簡單。以下所示的 ASP.NET 網頁便是使用自訂快取相依性類別來擷取並顯示使用 ASP.NET Xml 控制項的 RSS 餵送。程式碼會測試以確定快取中是否包含屬於輸入 URL 的項目。如果沒有,程式碼將設定標籤文字來指出項目並未從快取中提取,接著會建立 BlogCacheDependency 類別的新執行個體 (在 RSS 餵送的 URL 中傳遞),以及輪詢間的秒數 (此例為 3600 秒,即一小時)。接著根據使用者所指定的 URL 索引鍵和相依性執行個體的 RSS 屬性值,會將項目插入 Cache 中,並將快取項目設為與該相依性執行個體相關。最後,程式碼會對快取項目設定 Xml 控制項的 Document 屬性,並將 TransformSource 屬性設為 "feeds.xsl",這是我在 today.icantfocus.com 網站 (http://today.icantfocus.com/blog/archives/entries/000430/) 找到的 XSL 樣式表,可將 RSS 轉換成 HTML。
<%@ page language="VB" %> <%@ import namespace="v2_Caching" %> <script runat="server"> Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Label2.Text = "Yes" If Cache(TextBox1.Text) Is Nothing Then Label2.Text = "No" 'create dependency to poll for changes every 60 minutes. Dim dep As New BlogCacheDependency(TextBox1.Text, 3600) Cache.Insert(TextBox1.Text, dep.RSS, dep) End If FeedXml.Document = Cache(TextBox1.Text) FeedXml.TransformSource = "feeds.xsl" End Sub </script> <html> <head runat="server"> <title>Custom Cache Dependency Example</title> </head> <body> <form runat="server"> Enter the RSS feed to display: <asp:textbox id="TextBox1" runat="server"> </asp:textbox> <asp:button id="Button1" onclick="Button1_Click" runat="server" text="Get Feed" /> <hr /> Served from cache: <asp:label id="Label2" runat="server" forecolor="#FF3366"> </asp:label> <br /> Feed: <asp:xml id="FeedXml" runat="Server" /> <br /> </form> </body> </html>
[圖 1] 顯示網頁的外觀。
[圖 1] CustomDependency.aspx
當使用者輸入有效的餵送 URL (請注意,本範例不會驗證 URL,因此如果輸入無效的 URL,將會產生例外),並按一下 [取得餵送 (Get Feed)] 按鈕,將得到類似 [圖 2] 的結果 (請注意,餵送不是從快取中提取)。
[圖 2] 顯示 Blog 餵送
在接下來的要求中,Feed 將由快取提供,如 [圖 3] 所示。
[圖 3] 由快取提供餵送
如果餵送發生變更,那麼 Timer 程式碼會在下次輪詢間隔時驗證快取的項目,其結果如 [圖 4] 所示。
[圖 4] 更新的餵送
在開發自訂快取相依性時,最後要提醒您:每當開發輪詢外部資源的程式碼時 — 尤其是您無法掌控的外部資源 — 您必須謹記以下兩點:
- 您應該格外留意輪詢機制對外部資源造成的負擔。每隔 30 秒就輪詢他人管理的 RSS 餵送可能會引起不滿,特別是大部分 RSS 餵送的更新頻率都不會這麼頻繁。
- 您應該加併例外處理程式碼,以應付有時難免無法取得輪詢之 RSS 餵送的情況。
SQL 快取失效
資料與輸出快取提供給網路開發人員最大的便利之一,就是能夠避免產生每個要求的處理成本或避免擷取每個要求的費時資源。當然,資料庫的往返通常是最費時的資源之一,因此對於儲存記憶體中的資料集內容或資料導向網頁的擷取版本而言,快取功能特別有用。
但是當您需要取得最新資料的網頁時,問題就來了。ASP.NET v1.1 並未提供內建機制可確保快取資料不會過時,除非您設定非常短期的快取持續期間,或使用部分網頁快取功能, 以便專門快取不會變動的網頁部分內容。
ASP.NET Whidbey 的對策是根據 Microsoft® SQL Server™ 資料的變更來支援失效的快取項目或輸出快取網頁。這個功能的實作方法相當簡單,而且已經獲得 SQL Server 7、2000 及 Yukon 的支援。
SQL Server 7/2000
ASP.NET 團隊要在 SQL Server 7 和/或 2000 中提供資料庫快取失效方面,所面臨挑戰之一是:當特定表格的資料變更時,這兩個版本都未提供內建的機制,以便通知相關人員。當然,此時可以使用觸發程序來建立入侵作業 (我曾使用某個入侵作業讓觸發程序呼叫 sp_MakeWebTask,使得 SQL Server Web 輔助程式將表格內容寫入網頁,然後我再使用該網頁作為檔案快取相依性),但您必須承擔如果發生封鎖情況,網站將完全無法運作的風險,更遑論提升執行效能。
從上述範例中,您已經大致瞭解其解決方案。ASP.NET 團隊整合了名為 SqlCacheDependency 類別的自訂快取相依性,這個類別會根據您指定的排程,輪詢特定資料庫並尋找變更。如果發現資料已經變更,它會使快取無效,而您將取得最新的資料。
為了簡化輪詢和比較機制,您必須在 SQL 7/2000 的 SQL 快取失效中,為每個要監視變更的資料庫/表格進行一次設定。這項設定是利用 aspnet_regsqlcache.exe 命令列工具來執行 (這是 Whidbey Alpha 版的個別功能,但是將合併至另一個工具 (aspnet_regsql.exe) 中,這個工具預計將於 Beta 版中提供精靈及命令列 UI)。您可以在 Whidbey 版本的基本架構目錄中找到 aspnet_regsqlcache.exe。
啟用 Pubs 範例資料庫的快取失效很簡單,只要執行下列命令即可 (-S 參數會指定本機 SQL Server 執行個體,而 -E 參數會告訴公用程式透過使用者信任連線來連接 SQL Server,因此您的登入帳戶必須能夠存取 SQL Server 機器和要連接的資料庫):
aspnet_regsqlcache.exe -S (local) -E -d Pubs –ed
啟用作者資料表很簡單,只要執行下列程式碼即可:
aspnet_regsqlcache.exe -S (local) -E -d Pubs -t Authors –et
您可以執行:
aspnet_regsqlcache.exe -?
...藉此檢視所有可用的命令列參數。
一旦設定資料庫之後,您便需要指定連線資訊和輪詢頻率。我們會利用 web.config 中一個新的組態項目 (稱為 <cache>) 來進行,如下所示 (connectionStrings 區段也是 ASP.NET Whidbey 的新內容,是用來儲存應用程式所使用的連接字串。請注意,Beta 版預計將加入加密使用者識別碼和密碼資訊的支援)。
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <connectionStrings> <add name="PubsConnYukon" connectionString="User ID=<id>;pwd=<password>;Initial
Catalog=pubs;Data Source=192.168.0.108" /> <add name="PubsConn" connectionString="Initial Catalog=pubs;Data
Source=(local);Trusted_Connection=true" /> </connectionStrings> <system.web> <cache> <sqlCacheDependency enabled="true" pollTime="30000"> <databases> <add name="Pubs" connectionStringName="PubsConn" /> </databases> </sqlCacheDependency> </cache> </system.web> </configuration>
在上述範例中,我們已經討論過啟用資料庫快取相依性 (應用程式的通用設定) 的 <sqlCacheDependency> 項目,並將預設輪詢時間設為 30000 毫秒 (30 秒)。<databases> 項目包含所有針對此應用程式設定的資料庫,而本例只有一個 <add> 項目,該項目會使用 connectionStringName 屬性加入 Pubs 資料庫 (您也可以使用 connectionString 屬性,直接在 <add> 項目中指定連接字串)。名稱屬性會指定稍後用來參考此相依性的名稱。
一旦設定 <cache> 項目之後,您很容易就可以使用設定好的相依性。相依性可以透過三種方法進行設定:輸出快取區 API 、快取區或使用宣告方式。
下列程式碼顯示我們要如何透過輸出快取區 API 來使用相依性,以便在 Authors 資料表的資料變更時,使網頁的輸出快取失效。
注意 這段程式碼假設已經匯入 System.Web.Caching 命名空間。
Dim sqlDependency As New SqlCacheDependency("Pubs", "Authors") Response.AddCacheDependency(sqlDependency) Response.Cache.SetValidUntilExpires(True) Response.Cache.SetExpires(DateTime.Now.AddMinutes(60)) Response.Cache.SetCacheability(HttpCacheability.Public)
這段程式碼通常會寫在 age_Load 事件處理常式中。
若要使用已設定的相依性搭配 Cache 類別,我們將使用以下程式碼,可能似曾相識。這段程式碼會從 Pubs Authors 資料表擷取資料集,並使用已設定的 SqlCacheDependency 來快取資料集,如果資料沒有變更,則只會傳回快取的資料集。
Dim Key As String = "Authors" If (Cache(Key) Is Nothing) Then Label1.Text = "Not in Cache? Dim connection As New _ SqlConnection(ConfigurationSettings.ConnectionStrings("Pubs")) Dim adapter As New _ SqlDataAdapter("SELECT * FROM Authors", connection) Dim DS As New DataSet adapter.Fill(dataSet) Cache.Insert(Key, DS, New SqlCacheDependency("Pubs", "Products")) Else Label1.Text = "In Cache? End If Return Cache(Key)
最後,我們也可以直接使用宣告式 @ OutputCache
指示詞來快取整個網頁輸出,並使用新的 sqlDependency 屬性來指定相依性,所使用的格式為 DatabaseAlias:TableName,其中,DatabaseAlias 是根據我們在 web.config 中設定之 <add> 項目的屬性名稱所指定的名稱,而 TableName 則是要輪詢變更的表格名稱。下列程式碼顯示的網頁會遵循我們稍早設定的相依性,並從 Authors 資料表提取資料、將資料繫結到 GridView 控制項,然後再快取網頁輸出:
<%@ page language="VB" %> <%@ outputcache duration="9999" varybyparam="none" sqldependency="Pubs:Authors" %> <script runat="server"> Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Sqldatasource1.ConnectionString = _ ConfigurationSettings.ConnectionStrings("PubsConn") CacheStatus.Text = "This page was last rendered at: " & _ DateTime.Now.ToLongTimeString End Sub </script> <html> <head runat="server"> <title>DB Cache invalidation on SQL Server 2000</title> </head> <body> <form runat="server"> <h2><asp:label id="CacheStatus" runat="Server"/></h2> <asp:gridview id="Gridview1" datasourceid="Sqldatasource1" bordercolor="#CC9966" borderstyle="None" borderwidth="1px" backcolor="White" cellpadding="4" runat="server"> <alternatingrowstyle font-italic="False" font-bold="False"> </alternatingrowstyle> <rowstyle forecolor="#330099" backcolor="White" font-italic="False" font-bold="False"> </rowstyle> <headerstyle forecolor="#FFFFCC" backcolor="#990000" font-italic="False" font-bold="True"> </headerstyle> <footerstyle forecolor="#330099" backcolor="#FFFFCC" font-italic="False" font-bold="False"> </footerstyle> </asp:gridview> <asp:sqldatasource id="Sqldatasource1" runat="server" selectcommand="SELECT * FROM authors" providername="System.Data.SqlClient" > </asp:sqldatasource> </form> </body> </html>
上述網頁 (也可從本文的範例程式碼中取得) 會快取其輸出,直到 Authors 資料表中的資料發生變更。接著該網頁會擷取更新的資料,並再次快取網頁輸出。
SQL Server "Yukon"
SQL Server "Yukon" 新的通知基礎結構,讓您更容易使用資料庫快取失效。處理 Yukon 資料時,您是利用 SqlCacheDependency 類別上的建構函式多載,來建構以擷取資料所用之 SqlCommand 執行個體為基礎的相依性。其中,這項作業會建立接聽項物件來接收來自 Yukon 資料庫伺服器的通知訊息,並將應用程式登記為資料變更通知的訂閱者。收到這類通知時,便會移除與相依性相關的快取項目。
Yukon 所提供的通知服務,其優點在於免除了使用特殊表格、觸發程序和預存程序來設定資料庫的必要性;而且也不需要特別設定 web.config,因為 Yukon 並不一定要執行輪詢。若要使用 Yukon 來發揮資料庫快取失效的優勢,您只需加入一行程式碼,以產生 SqlCommand (用來擷取資料) 與 SqlCacheDependency 類別之執行個體的關聯:
Dim SqlDep As New SqlCacheDependency(SqlCmd)
...然後您便可以在 SQL Server 7 或 2000 中使用相依性。因此,使用輸出快取來快取網頁時,程式碼看起來如下所示 (本文的範例檔案中的網頁 SqlCacheInvalidation_Yukon.aspx 也使用這段程式碼):
Dim SqlConn As New _ SqlConnection(ConfigurationSettings.ConnectionStrings("PubsConnYukon")) Dim SqlCmd As New SqlCommand("SELECT * FROM Authors", SqlConn) Dim SqlDep As New SqlCacheDependency(SqlCmd) SqlConn.Open() Gridview1.DataSource = SqlCmd.ExecuteReader() Gridview1.DataBind() SqlConn.Close() Response.AddCacheDependency(sqlDependency) Response.Cache.SetValidUntilExpires(True) Response.Cache.SetExpires(DateTime.Now.AddMinutes(60)) Response.Cache.SetCacheability(HttpCacheability.Public)
使用 Cache 類別來快取資料集的程式碼看起來不太一樣,但仍是運用相同的基本概念 (以粗體顯示的程式碼代表產生命令與 SqlCacheDependency 的關聯):
Dim Key As String = "Authors" If (Cache(Key) Is Nothing) Then Label1.Text = "Not in Cache? Dim connection As New _ SqlConnection(ConfigurationSettings.ConnectionStrings("Pubs")) Dim adapter As New _ SqlDataAdapter("SELECT * FROM Authors", connection) Dim DS As New DataSet adapter.Fill(dataSet) Cache.Insert(Key, DS, New SqlCacheDependency(adapter.SelectCommand)) Else Label1.Text = "In Cache? End If Return Cache(Key)
重點大致已說明完畢。當然,還是有些限制必須注意。首先是在 Yukon 資料庫中用來存取資料的帳戶必須具有足夠的權限,以便要求目標資料庫的查詢通知訂閱 (Query Notification Subscriptions)。其次,由於 Yukon 的 PDC 組建的錯誤,唯有使用 sa 帳戶登入資料庫,才會傳送資料變更的通知。
重要事項 基於眾所皆知的原因,您「不」應該在任何應用程式中使用 sa 帳戶來存取資料或進行修改。因此,如果您想在 Yukon 的 PDC 組建中測試 SQL 快取失效的功能,請務必只在無法存取網際網路 (包括 Web 伺服器及資料庫伺服器) 的應用程式上進行。
快取後置替換
我要介紹的最後一項新功能稱為快取後置替換 (Post-cache Substitution),這項功能可與其他功能相輔相成。您會希望在許多應用程式中運用輸出快取的功能,但是一點點動態程式碼實在不適用快取。然而藉由快取後置替換,您可以在網頁中加入類似替代符號的控制項,並讓此控制項呼叫特定方法,以便在 Runtime 時傳回字串輸出。這麼一來,您就可以盡情享用 Cake (呃,我是說「快取 (Cache)」)!
快取後置替換也是最容易上手的新功能。有兩種方式可供您選擇替換位置:
- 呼叫新的 Response.WriteSubstitution 方法,再將想要使用的替換方法回呼參考傳遞給它。
- 將 <asp:substitution> 控制項在想要的位置加入網頁,並將其 methodname 屬性設定為回呼方法的名稱。
第二項技巧的優點在於可讓您更精確地指定要呈現字串輸出的位置。無論使用哪種方法,您都要在網頁中加入 @ OutputCache
指示詞,以便指定快取網頁輸出的持續期間、位置等等。快取後置替換的另一項特點是,可讓您撰寫自訂控制項來充分發揮這項功能。例如,ASP.NET 團隊重新撰寫了 AdRotator 控制項,好讓它能感知快取後置替換。這表示如果 AdRotator 控制項加入網頁,接著再輸出快取該網頁,則 AdRotator 控制項將自動執行快取後置替換,並正確顯示您所指定的廣告,完全不需要麻煩您!
下列程式碼顯示使用快取後置替換的網頁範例。該網頁會從 Pubs 資料庫的作者資料表擷取資料,並將資料繫結至 GridView,然後透過 AdRotator 控制項顯示廣告。網頁包含寫入網頁建立時間的標籤 (在 Page_Load 中)。我還在網頁中加入 <asp:substitution> 控制項,並將其 Methodname 屬性設為 Substitute;這是會傳回所要字串輸出的方法名稱 — 在本例中,則只是包含目前時間的字串:
<%@ page language="VB" %> <%@ outputcache duration="30" varybyparam="none" %> <script runat="server" language="vb"> Shared Function Substitute(ByVal MyContext As HttpContext) As String Dim str As String = "I'm adding content to a cached page!<br/>" str &= "The Current Time is: " & DateTime.Now.ToLongTimeString Return str End Function Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) SqlDataSource1.ConnectionString = _ ConfigurationSettings.ConnectionStrings("PubsConn") Label1.Text = "Page created at: " + DateTime.Now.ToLongTimeString End Sub </script> <html> <head id="Head1" runat="server"> <title>Untitled Page</title> </head> <body> <form id="Form1" runat="server"> <h1> <asp:label id="Label1" runat="server">Label</asp:label> </h1> <br /> <br /> <asp:adrotator id="AdRotator1" width="468px" height="60px" advertisementfile="ads_tall.xml" runat="server" /> <asp:substitution id="Substitution1" methodname="Substitute" runat="server" /> <br /> <br /> <asp:gridview id="GridView1" autogeneratecolumns="False" datasourceid="SqlDataSource1" datakeynames="au_id" runat="server" > <columnfields> <asp:boundfield sortexpression="au_id" datafield="au_id" readonly="True" headertext="Author ID"> </asp:boundfield> <asp:boundfield sortexpression="au_fname" datafield="au_fname" headertext="First Name"> </asp:boundfield> <asp:boundfield sortexpression="au_lname" datafield="au_lname" headertext="Last Name"> </asp:boundfield> </columnfields> <rowstyle forecolor="#000066"> </rowstyle> <headerstyle forecolor="White" backcolor="#006699" font-bold="True"> </headerstyle> </asp:gridview> <asp:sqldatasource id="SqlDataSource1" providername="System.Data.SqlClient" selectcommand="SELECT [au_id], [au_fname], [au_lname] FROM dbo.[authors]" runat="server" > </asp:sqldatasource> </form> </body> </html>
第一次呼叫時,此網頁會傳回 [圖 5] 所示的輸出。(請注意 "page created" 標籤會與替換方法的時間輸出相符)。
[圖 5] PostCache.aspx 的初始輸出
重新整理網頁時,您會發現即使執行輸出快取,AdRotator 輸出和 Substitute 方法的輸出都會經過更新,而網頁的他部分則維持快取狀態,如 [圖 6] 所示。
[圖 6] 使用快取後置替換的快取輸出
本文的範例檔案也涵蓋名為 PostCache_RWS.aspx 並使用 Response.WriteSubstitution 的網頁,有興趣者可參考此技巧。
結論
憑著新加入的一些簡易功能,ASP.NET 團隊進一步改良了 ASP.NET 原本就實用的部分。有了下列功能:
- 快取資料導向網頁輸出或資料集,並自動清除已修改資料的快取
- 建立自訂的快取相依性
- 透過快取後置替換,在 Runtime 時以動態方式將文字片段加入快取的網頁中
...ASP.NET 應用程式開發人員再也找不到藉口來逃避使用快取功能。如此一來,新一代 ASP.NET 應用程式的效能必定優異非凡。