ASP.NET 2.0 中改進(jìn)的緩存功能

2010-08-28 10:50:18來源:西部e網(wǎng)作者:

對于由數(shù)據(jù)庫驅(qū)動(dòng)的 Web 應(yīng)用程序來說,要改進(jìn)其性能,最好的方法就是使用緩存。從數(shù)據(jù)庫中檢索數(shù)據(jù)可能是您在 Web 站點(diǎn)上執(zhí)行的最慢的操作之一。如果能夠?qū)?shù)據(jù)庫中的數(shù)據(jù)緩存到內(nèi)存中,就無需在請求每個(gè)頁面時(shí)都訪問數(shù)據(jù)庫,從而可以大大提高應(yīng)用程序的性能。

緩存有一個(gè)且只有一個(gè)缺點(diǎn),那就是數(shù)據(jù)過期的問題。如果將數(shù)據(jù)庫表的內(nèi)容緩存到內(nèi)存中,當(dāng)基礎(chǔ)數(shù)據(jù)庫表中的記錄發(fā)生更改時(shí),您的 Web 應(yīng)用程序?qū)@示過期的、不準(zhǔn)確的數(shù)據(jù)。對于某些類型的數(shù)據(jù),即便顯示的數(shù)據(jù)稍微有些過期,影響也不會(huì)太大;但對于諸如股票價(jià)格和競拍出價(jià)之類的數(shù)據(jù),即使顯示的數(shù)據(jù)稍微有些過期也是不可接受的。

Microsoft ASP.NET 1.0 Framework 沒有針對此問題提供一個(gè)完善的解決方案。使用 ASP.NET 1.0 Framework 時(shí),您不得不在性能和數(shù)據(jù)過期之間作出權(quán)衡。幸運(yùn)的是,Microsoft ASP.NET 2.0 Framework 提供了一項(xiàng)新功能,稱為 SQL Cache Invalidation,可以解決這一棘手的問題。

在本文中,您將進(jìn)一步了解 ASP.NET 2.0 Framework 中許多新的緩存改進(jìn)功能。首先,您將了解到如何在新增的 DataSource 控件中集成緩存支持。然后,您將了解到如何配置和使用 SQL Cache Invalidation。最后,您將了解到隨 ASP.NET 2.0 Framework 引入的一個(gè)新控件:Substitution 控件,使用該控件可以向已緩存的頁面中插入動(dòng)態(tài)內(nèi)容。

更輕松的數(shù)據(jù)緩存

在 ASP.NET 2.0 Framework 中,最大的變化之一就是在 ASP.NET 頁面上訪問數(shù)據(jù)庫數(shù)據(jù)的方式發(fā)生了變化。ASP.NET 2.0 Framework 包含一組新的控件,統(tǒng)稱為 DataSource 控件。您可以使用這些控件來表示數(shù)據(jù)源,例如數(shù)據(jù)庫或 XML 文件。

在 ASP.NET 1.0 Framework 中,是通過將控件綁定到 DataSetDataReader,使用控件來顯示數(shù)據(jù)庫數(shù)據(jù)的。而在 ASP.NET 2.0 Framework 中,通常是將控件綁定到 DataSource 控件。通過 DataSource 控件,您可以創(chuàng)建顯示數(shù)據(jù)庫數(shù)據(jù)的 ASP.NET 頁面,而不用為訪問數(shù)據(jù)庫編寫任何代碼。

在處理數(shù)據(jù)庫數(shù)據(jù)時(shí),通常使用下列三個(gè) DataSource 控件中的一個(gè)控件:

SqlDataSource — 表示 SQL 數(shù)據(jù)源,例如 Microsoft SQL Server 或 Oracle 數(shù)據(jù)庫。

AccessDataSource — 一個(gè)專用的 SqlDataSource 控件,用于 Microsoft Access 數(shù)據(jù)庫。

ObjectDataSource — 表示充當(dāng)數(shù)據(jù)源的自定義業(yè)務(wù)對象。

例如,假設(shè)您要在 DropDownList 控件中顯示從數(shù)據(jù)庫中檢索到的書目列表(參見圖 1)。列表 1 中的頁面說明了如何將 DropDownList 控件綁定到 SqlDataSource 控件。

\

1使用 SqlDataSource 控件檢索數(shù)據(jù)

列表 1DisplayTitles.aspx

<html>
<head runat="server">
<title>Display Titles</title>
</head>
<body>
<form id="form1" runat="server">

<asp:DropDownList 
ID="DropDownList1" 
DataSourceId="SqlDataSource1"
DataTextField="Title"
Runat="server" />
     
<asp:SqlDataSource 
ID="SqlDataSource1"
ConnectionString="Server=localhost;database=Pubs"
SelectCommand="SELECT Title FROM Titles"
Runat="server" />
    
</form>
</body>
</html>

請注意,列表 1 中的 SqlDataSource 控件用于提供連接字符串,SQL SELECT 命令用于從數(shù)據(jù)庫中檢索記錄。DropDownList 控件通過其 DataSourceID 屬性綁定到 SqlDataSource 控件。

使用 DataSource 控件緩存數(shù)據(jù)

使用 DataSource 控件,不僅可以更輕松地連接數(shù)據(jù)庫,還使緩存數(shù)據(jù)庫數(shù)據(jù)變得更容易。只需在 SqlDataSource 控件上設(shè)置一兩個(gè)屬性,就可以自動(dòng)在內(nèi)存中緩存由 DataSource 控件表示的數(shù)據(jù)。

例如,如果要將 Titles 數(shù)據(jù)庫表在內(nèi)存中緩存至少 10 分鐘,可以按照以下方式聲明 SqlDataSource 控件。

 <asp:SqlDataSource 
ID="SqlDataSource1"
EnableCaching="true"
CacheDuration="600"
ConnectionString="Server=localhost;database=Pubs"
SelectCommand="SELECT Title FROM Titles"
Runat="server" />

如果 EnableCaching 屬性的值為 true,SqlDataSource 將自動(dòng)緩存通過 SelectCommand 檢索到的數(shù)據(jù)。使用 CacheDuration 屬性,可以指定從數(shù)據(jù)庫中刷新數(shù)據(jù)之前緩存數(shù)據(jù)的時(shí)間(以秒為單位)。

默認(rèn)情況下,SqlDataSource 使用絕對過期策略來緩存數(shù)據(jù),即每隔指定的秒數(shù)就從數(shù)據(jù)庫中刷新一次。此外,您還可以選擇使用可變過期策略。如果將 SqlDataSource 配置為使用可變過期策略,那么只要持續(xù)訪問數(shù)據(jù),數(shù)據(jù)就不會(huì)過期。如果需要緩存大量項(xiàng)目,使用可變過期策略將非常有用,因?yàn)檫@種過期策略將只在內(nèi)存中保留訪問最頻繁的項(xiàng)目。

例如,下面的 SqlDataSourceControl 被配置為使用可變過期策略,過期時(shí)間為 10 分鐘。

<asp:SqlDataSource 
ID="SqlDataSource1"
EnableCaching="true"
CacheExpirationPolicy="Sliding"
CacheDuration="600"
ConnectionString="Server=localhost;database=Pubs"
SelectCommand="SELECT Title FROM Titles"
Runat="server" />

由于 CacheExpirationPolicy 屬性的值被設(shè)置為 Sliding,CacheDuration 屬性的值被設(shè)置為 600,因此,只要在 10 分鐘內(nèi)持續(xù)訪問,此 SqlDataSource 表示的數(shù)據(jù)就會(huì)一直保留在內(nèi)存中。

 

使用 SQL Cache Invalidation

SQL Cache Invalidation 是 ASP.NET 2.0 Framework 最值得期待的新增功能之一。使用 SQL Cache Invalidation 可以獲得緩存的全部性能優(yōu)勢,而不用擔(dān)心數(shù)據(jù)過期的問題。SQL Cache Invalidation 使您可以在基礎(chǔ)數(shù)據(jù)庫中的數(shù)據(jù)發(fā)生更改時(shí)自動(dòng)更新緩存中的數(shù)據(jù)。

SQL Cache Invalidation 通過在后臺不斷輪詢數(shù)據(jù)庫來檢查數(shù)據(jù)更改。每隔一定的時(shí)間(毫秒),ASP.NET Framework 就會(huì)檢查數(shù)據(jù)庫中是否存在更新。如果 ASP.NET Framework 檢測到任何更改,將從緩存中刪除從數(shù)據(jù)庫中添加的、依賴于數(shù)據(jù)庫的任何項(xiàng)目(即,這些項(xiàng)目將過期)。

注意:Microsoft SQL Server 2005 支持一種截然不同的 SQL Cache Invalidation 方法。您可以配置 SQL Server 2005,使其在數(shù)據(jù)庫、數(shù)據(jù)庫表或數(shù)據(jù)庫行發(fā)生變化時(shí)通知 ASP.NET 應(yīng)用程序。這樣,ASP.NET Framework 就不需要通過不斷輪詢 SQL Server 2005 數(shù)據(jù)庫來檢查數(shù)據(jù)更改了。

需要注意的是,SQL Cache Invalidation 只能用于 Microsoft SQL Server 7 及更高版本,不能用于其他數(shù)據(jù)庫,例如 Microsoft Access 或 Oracle。

在緩存整個(gè)頁面的輸出、使用 DataSource控件或直接使用 Cache 對象時(shí),都可以使用 SQL Cache Invalidation。下面將分別介紹這三種情況。

配置 SQL Cache Invalidation

在 Web 應(yīng)用程序中使用 SQL Cache Invalidation 之前,首先必須執(zhí)行一些配置步驟。必須將 Microsoft SQL Server 配置為支持 SQL Cache Invalidation,還必須在應(yīng)用程序的 Web 配置文件中添加必要的配置信息。

可以按照以下兩種方法配置 SQL Server:使用 aspnet_regsql 命令行工具,或者使用 SqlCacheDependencyAdmin 類。

使用 ASPNET_REQSQL 啟用 SQL Cache Invalidation

使用 aspnet_regsql 工具,您可以通過命令行來配置 SQL Cache Invalidation。aspnet_regsql 工具位于 Windows\Microsoft.NET\Framework\[版本] 文件夾中。要使用此工具,必須打開命令提示符窗口并瀏覽到此文件夾。

要在使用 Pubs 數(shù)據(jù)庫時(shí)支持 SQL Cache Invalidation,需要執(zhí)行以下命令。

aspnet_regsql -E -d Pubs -ed

-E 選項(xiàng)使 aspnet_regsql 工具在連接到數(shù)據(jù)庫服務(wù)器時(shí)使用集成的安全設(shè)置。-d 選項(xiàng)用于選擇 Pubs 數(shù)據(jù)庫。最后,-ed 選項(xiàng)用于為數(shù)據(jù)庫啟用 SQL Cache Invalidation。

執(zhí)行此命令時(shí),將在數(shù)據(jù)庫中添加一個(gè)名為 AspNet_SqlCacheTablesForChangeNotification 的新數(shù)據(jù)庫表。此表包含啟用了 SQL Cache Invalidation 的所有數(shù)據(jù)庫表的列表。此命令還將在數(shù)據(jù)庫中添加一組存儲過程。

為數(shù)據(jù)庫啟用 SQL Cache Invalidation 后,必須從數(shù)據(jù)庫中選擇要啟用 SQL Cache Invalidation 的特定表。以下命令將為 Titles 數(shù)據(jù)庫表啟用 SQL Cache Invalidation。

aspnet_regsql -E -d Pubs -t Titles -et

-t 選項(xiàng)用于選擇數(shù)據(jù)庫表。-et 選項(xiàng)為數(shù)據(jù)庫表啟用 SQL Cache Invalidation。當(dāng)然,您可以通過對每個(gè)數(shù)據(jù)庫表重復(fù)執(zhí)行此命令,為多個(gè)表啟用 SQL Cache Invalidation。

執(zhí)行此命令時(shí),將在數(shù)據(jù)庫表中添加一個(gè)觸發(fā)器。只要您對表進(jìn)行了修改,此觸發(fā)器就將觸發(fā)并更新 AspNet_SqlCacheTablesForChangeNotification 表。

最后,要獲取某個(gè)特定數(shù)據(jù)庫中當(dāng)前啟用了 SQL Cache Invalidation 的表的列表,可以使用以下命令。

aspnet_regsql -E -d Pubs -lt

此方法將從 AspNet_SqlCacheTablesForChangeNotification 中選擇表的列表。此外,您也可以通過直接在該數(shù)據(jù)庫表中執(zhí)行查詢來檢索此信息。

使用 SqlCacheDependencyAdmin 類

aspnet_regsql 工具在后臺使用 SqlCacheDependencyAdmin 類的方法來配置 Microsoft SQL Server。如果您愿意,可以直接從 ASP.NET 頁面中使用此類的方法。

SqlCacheDependencyAdmin 類具有五個(gè)重要的方法:

DisableNotifications — 為特定數(shù)據(jù)庫禁用 SQL Cache Invalidation。

DisableTableForNotifications — 為數(shù)據(jù)庫中的特定表禁用 SQL Cache Invalidation。

EnableNotifications — 為特定數(shù)據(jù)庫啟用 SQL Cache Invalidation。

EnableTableForNotifications — 為數(shù)據(jù)庫中的特定表啟用 SQL Cache Invalidation。

GetTablesEnabledForNotifications — 返回啟用了 SQL Cache Invalidation 的所有表的列表。

例如,使用列表 2 中的 ASP.NET 頁面,您可以為 Pubs 數(shù)據(jù)庫中的任何表配置 SQL Cache Invalidation(參見圖 2)。

\

2從 ASP.NET 頁面中啟用 SQL Cache Invalidation

列表 2EnableSCI.aspx (C#)

<%@ Page Language="c#" %>
<%@ Import Namespace="System.Web.Caching" %>
<script runat="server">

const string connectionString = "Server=localhost;Database=Pubs";

void Page_Load()
    {
if (!IsPostBack)
        {
SqlCacheDependencyAdmin.EnableNotifications(
connectionString);
SqlDataSource1.SelectParameters.Add("connectionString", 
connectionString);
        }
    }

void EnableTable(Object s, EventArgs e)
    {
try
        {
SqlCacheDependencyAdmin.EnableTableForNotifications(
connectionString, txtTableName.Text);
        }
catch (Exception ex)
        {
lblErrorMessage.Text = ex.Message;
        }
txtTableName.Text = "";
    }

</script>

<html>
<head runat="server">
<title>Enable SQL Cache Invalidation</title>
</head>
<body>
<form id="form1" runat="server">
    
<h1>SQL Cache Invalidation</h1>

以下表格已啟用 SQL Cache Invalidation:

<p>
<asp:GridView id="grdTables" 
DataSourceID="SqlDataSource1" CellPadding="10" 
ShowHeader="false" Runat="Server" />
</p>
    
<asp:ObjectDataSource 
ID="SqlDataSource1" 
TypeName="System.Web.Caching.SqlCacheDependencyAdmin"
SelectMethod="GetTablesEnabledForNotifications"
Runat="Server" />
<p>
<asp:Label ID="lblErrorMessage" EnableViewState="false" 
ForeColor="red" Runat="Server" />
</p>

<asp:TextBox ID="txtTableName" Runat="Server" /> 
<asp:Button Text="Enable Table" OnClick="EnableTable" 
Runat="Server" /> 
 
</form>
</body>
</html>

列表 2EnableSCI.aspx (Visual Basic .NET)

<%@ Page Language="vb" %>
<%@ Import Namespace="System.Web.Caching" %>
<script runat="server">

Const connectionString As String = "Server=localhost;Database=Pubs"

Sub Page_Load()
    
If Not IsPostBack Then
SqlCacheDependencyAdmin.EnableNotifications( _
connectionString)
SqlDataSource1.SelectParameters.Add("connectionString", _
connectionString)
End If
End Sub

Sub EnableTable(ByVal s As Object, ByVal e As EventArgs)
    
Try
        
SqlCacheDependencyAdmin.EnableTableForNotifications( _
connectionString, txtTableName.Text)
Catch ex As Exception
lblErrorMessage.Text = ex.Message
End Try
txtTableName.Text = ""
End Sub

</script>

<html>
<head id="Head1" runat="server">
<title>ConfigureSCI</title>
</head>
<body>
<form id="form1" runat="server">
    
<h1>SQL Cache Invalidation</h1>

以下表格已啟用 SQL Cache Invalidation:

<p>
<asp:GridView id="grdTables" DataSourceID="SqlDataSource1" 
CellPadding="10" ShowHeader="false" Runat="Server" />
</p>
    
<asp:ObjectDataSource 
ID="SqlDataSource1" 
TypeName="System.Web.Caching.SqlCacheDependencyAdmin"
SelectMethod="GetTablesEnabledForNotifications"
Runat="Server" />
<p>
<asp:Label ID="lblErrorMessage" EnableViewState="false" 
ForeColor="red" Runat="Server" />
</p>

<asp:TextBox ID="txtTableName" Runat="Server" /> 
<asp:Button ID="Button1" Text="Enable Table" 
OnClick="EnableTable" Runat="Server" /> 
 
</form>
</body>
</html>

在列表 2 中,connectionString 常量用于選擇啟用了 SQL Cache Invalidation 的數(shù)據(jù)庫(如果要為 Pubs 數(shù)據(jù)庫以外的數(shù)據(jù)庫啟用 SQL Cache Invalidation,可以更改此常量的值)。在 Page_Load 方法中,調(diào)用 SqlCacheDependencyAdmin 類上的 EnableNotifications 方法,為由 connectionString 常量指定的數(shù)據(jù)庫啟用 SQL Cache Invalidation。

列表 2 中的 GridView 顯示了當(dāng)前啟用了 SQL Cache Invalidation 的所有數(shù)據(jù)庫表。GridView 被綁定到 ObjectDataSource 控件上,該控件為其 SelectMethod 調(diào)用 GetTablesneabledForNotifications 方法。

最后,您可以使用列表 2 中的頁面為其他表啟用 SQL Cache Invalidation。在文本框中輸入表的名稱并單擊“Enable Table”按鈕時(shí),將調(diào)用 EnableTableForNotifications 方法。

SQL Cache Invalidation 的 Web 配置設(shè)置

在 ASP.NET 應(yīng)用程序中使用 SQL Cache Invalidation 之前,下一步要做的是更新您的 Web 配置文件。您需要配置 ASP.NET Framework,以便輪詢啟用了 SQL Cache Invalidation 的數(shù)據(jù)庫。

列表 3 中的 Web 配置文件包含輪詢 Pubs 數(shù)據(jù)庫所必需的配置信息。

列表 3Web.Config

<configuration>
      
<connectionStrings>
<add name="mySqlServer" 
connectionString="Server=localhost;Database=Pubs" />
</connectionStrings>
        
<system.web>

<caching>
<sqlCacheDependency enabled="true">
<databases>
<add
name="Pubs"
connectionStringName="mySqlServer"
pollTime="60000" />
</databases>
</sqlCacheDependency>
</caching>
</system.web>
</configuration>

列表 3 中的 Web 配置文件包含兩部分。<connectionStrings> 部分用于創(chuàng)建數(shù)據(jù)庫連接字符串,以連接到名為 mySqlServer 的 Pubs 數(shù)據(jù)庫。

caching 部分用于配置 SQL Cache Invalidation 輪詢。在 <databases> 子部分中,您可以列出要對其進(jìn)行輪詢以檢查數(shù)據(jù)更改的一個(gè)或多個(gè)數(shù)據(jù)庫。在列表 3 中,mySqlServer 表示的數(shù)據(jù)庫每分鐘(每 60000 毫秒)輪詢一次。

您可以為不同的數(shù)據(jù)庫指定不同的輪詢間隔。每次輪詢數(shù)據(jù)庫以檢查數(shù)據(jù)更改時(shí),服務(wù)器都必須執(zhí)行一些操作。如果您認(rèn)為數(shù)據(jù)庫中的數(shù)據(jù)不會(huì)頻繁地更改,可以增加輪詢間隔。

在頁面輸出緩存中使用 SQL Cache Invalidation

現(xiàn)在,我們已經(jīng)完成了 SQL Cache Invalidation 的所有配置步驟,可以在 ASP.NET 頁面中使用它了。一種方法是在頁面輸出緩存中使用 SQL Cache Invalidation。頁面輸出緩存允許您在內(nèi)存中緩存頁面所顯示的所有內(nèi)容。通過使用 SQL Cache Invalidation,您可以在(且只在)數(shù)據(jù)庫表發(fā)生更改時(shí)自動(dòng)更新緩存的頁面。

例如,列表 4 中的頁面在 GridView 控件中顯示了 Titles 數(shù)據(jù)庫表的內(nèi)容。在該頁面的頂部,OutputCache 指令用于在內(nèi)存中緩存頁面內(nèi)容。如果 Titles 數(shù)據(jù)庫表發(fā)生更改,SqlDependency 屬性將使頁面更新。

列表 4OutputCacheTitles.aspx

<%@ OutputCache SqlDependency="Pubs:Titles" 
Duration="6000" VaryByParam="none" %>
<html>
<head runat="server">
<title>Output Cache Titles</title>
</head>
<body>
<form id="form1" runat="server">
    
<%= DateTime.Now %>

<asp:GridView 
ID="grdTitles" 
DataSourceID="SqlDataSource1" 
Runat="Server" />    
    
<asp:SqlDataSource
ID="SqlDataSource1"
SelectCommand="Select * FROM Titles"
ConnectionString="<%$ ConnectionStrings:mySqlServer %>"
Runat="Server" />
    
</form>
</body>
</html>

請注意,SqlDependency 屬性引用了 Web 配置文件中定義的數(shù)據(jù)庫的名稱。由于我們指定了每分鐘輪詢一次 Pubs 數(shù)據(jù)庫以檢查數(shù)據(jù)更改,因此如果對該數(shù)據(jù)庫進(jìn)行了更改,列表 4 中的頁面將在一分鐘之內(nèi)進(jìn)行更新。

您可以為 SqlDependency 屬性值列出多個(gè)數(shù)據(jù)庫和/或多個(gè)數(shù)據(jù)庫表。要?jiǎng)?chuàng)建多個(gè)依賴關(guān)系,只需用分號分隔每個(gè)依賴關(guān)系即可。

在 DataSource 控件中使用 SQL Cache Invalidation

除了在頁面輸出緩存中使用 SQL Cache Invalidation 之外,還可以直接在 DataSource 控件中使用 SQL Cache Invalidation。如果要在多個(gè)頁面中使用相同的數(shù)據(jù)庫數(shù)據(jù),請考慮在 DataSource 控件中使用 SQL Cache Invalidation。SqlDataSource、AccessDataSourceObjectDataSource 控件都支持 SqlCacheDependency 屬性。

例如,列表 5 中的頁面在 SqlDataSource 控件中使用了 SQL Cache Invalidation。

列表 5SqlDataSourceCaching.aspx

<html>
<head id="Head1" runat="server">
<title>SqlDataSource Caching</title>
</head>
<body>
<form id="form1" runat="server">

<%= DateTime.Now %>

<asp:GridView 
ID="grdTitles" 
DataSourceId="SqlDataSource1"
Runat="server" />
            
<asp:SqlDataSource 
ID="SqlDataSource1" 
EnableCaching="true"
SqlCacheDependency="Pubs:Titles"
SelectCommand="select * from titles"
ConnectionString="<%$ ConnectionStrings:mySqlServer %>"
Runat="server" />
   
</form>
</body>
</html>

在列表 5 中,SqlDataSource 控件是使用 EnableCachingSqlCacheDependency 這兩個(gè)屬性聲明的。SqlCacheDependency 屬性使用的語法與 OutputCache 指令的 SqlDependency 屬性相同。您需要列出數(shù)據(jù)庫的名稱,后跟數(shù)據(jù)庫表的名稱。

在 Cache 對象中使用 SQL Cache Invalidation

最后,您還可以在 Cache 對象中使用 SQL Cache Invalidation。此選項(xiàng)使您可以最大程度地對 SQL Cache Invalidation 進(jìn)行編程控制。

要在 Cache 對象中使用 SQL Cache Invalidation,您需要?jiǎng)?chuàng)建一個(gè) SqlCacheDependency 對象實(shí)例。使用 Insert 方法在 Cache 中插入新對象時(shí),可以使用 SqlCacheDependency 對象。

例如,列表 6 中的頁面顯示了 Titles 數(shù)據(jù)庫表中的記錄數(shù)。計(jì)數(shù)是基于對基礎(chǔ)數(shù)據(jù)庫表的依賴關(guān)系進(jìn)行緩存的。

列表 6DisplayTitleCount.aspx (C#)

<%@ Page Language="c#" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">

void Page_Load() 
    {
int count = 0;

if (Cache["TitleCount"] != null)
        {
count = (int)Cache["TitleCount"];
        }
else
        {
string connectionString = 
ConfigurationSettings.ConnectionStrings[
"mySqlServer"].ConnectionString;
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new 
SqlCommand("SELECT Count(*) FROM Titles", con);
con.Open();
count = (int)cmd.ExecuteScalar();
con.Close();
Cache.Insert("TitleCount", count, 
new SqlCacheDependency("Pubs", "Titles"));
        }
lblTitleCount.Text = count.ToString();
    }

</script>

<html>
<head runat="server">
<title>Display Title Count</title>
</head>
<body>
<form id="form1" runat="server">

<asp:Label ID="lblTitleCount" Runat="Server" />    
    
</form>
</body>
</html>

列表 6DisplayTitleCount.aspx (Visual Basic .NET)

<%@ Page Language="vb" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">

Sub Page_Load()
    
Dim count As Integer = 0

If Not Cache("TitleCount") Is Nothing Then
count = Convert.ToInt32(Cache("TitleCount"))
Else
Dim connectionString As String = _
ConfigurationSettings.ConnectionStrings( _
"mySqlServer").ConnectionString
Dim con As New SqlConnection(connectionString)
Dim cmd As New _
SqlCommand("SELECT Count(*) FROM Titles", con)
con.Open()
count = Convert.ToInt32(cmd.ExecuteScalar())
con.Close()
Cache.Insert("TitleCount", count, _
new SqlCacheDependency("Pubs", "Titles"))
End If
        
lblTitleCount.Text = count.ToString()
End Sub

</script>

<html>
<head id="Head1" runat="server">
<title>Display Titles Count</title>
</head>
<body>
<form id="form1" runat="server">

<asp:Label ID="lblTitleCount" Runat="Server" />    
    
</form>
</body>
</html>
 

使用 Post-Cache Substitution

在許多情況下,您需要緩存頁面的一部分,而不是整個(gè)頁面。例如,在您的 Web 站點(diǎn)主頁上,您可能希望同時(shí)顯示隨機(jī)的標(biāo)題廣告和數(shù)據(jù)庫表中的記錄。如果緩存整個(gè)頁面,每個(gè)用戶都將在每次請求的頁面上看到同一個(gè)標(biāo)題廣告。

要處理這種同時(shí)混有動(dòng)態(tài)內(nèi)容和緩存內(nèi)容的問題,一種方法是使用 Web 用戶控件。因?yàn)榭梢詾?Web 用戶控件添加 OutputCache 指令,所以即使不緩存包含頁面的內(nèi)容,也可以緩存 Web 用戶控件的內(nèi)容。

但有時(shí)候可能會(huì)事與愿違。雖然您可以使用 Web 用戶控件在動(dòng)態(tài)頁面上添加緩存的內(nèi)容,但很多情況下,您實(shí)際上是想在緩存的頁面中添加動(dòng)態(tài)內(nèi)容。例如,假設(shè)您要緩存整個(gè)頁面的內(nèi)容,只留一小塊區(qū)域用于顯示當(dāng)前用戶的用戶名。這種情況下最好使用 Post-Cache Substitution。

ASP.NET 2.0 Framework 引入了一種新控件,稱為 Substitution 控件。您可以使用 Substitution 控件在緩存的頁面中插入動(dòng)態(tài)內(nèi)容。列表 7 中的頁面使用 Substitution 控件將用戶名插入到緩存的內(nèi)容中(參見圖 3)。

\

3使用 Substitution 控件顯示用戶名

列表 7PostCacheSubstitution.aspx (C#)

<%@ Page Language="C#" %>
<%@ OutputCache Duration="6000" VaryByParam="none" %>

<script runat="server">

static string DisplayUsername(HttpContext context) 
    {
if (!context.Request.IsAuthenticated)
return "Anonymous";
else
return context.User.Identity.Name;
    }

</script>

<html>
<head runat="server">
<title>Post Cache Substitution</title>
</head>
<body>
<form id="form1" runat="server">
    
Welcome <asp:Substitution 
MethodName="DisplayUsername" Runat="Server" />!
    
<p>
此頁已緩存, 因?yàn)闀r(shí)間
<%= DateTime.Now.ToString("t") %> 并無改變。
</p>
        
</form>
</body>
</html>

列表 7PostCacheSubstitution.aspx (Visual Basic .NET)

<%@ Page Language="vb" %>
<%@ OutputCache Duration="6000" VaryByParam="none" %>

<script runat="server">

Shared Function DisplayUsername(ByVal context As HttpContext) _
As String
If Not context.Request.IsAuthenticated Then
Return "Anonymous"
Else
Return context.User.Identity.Name
End If
End Function

</script>

<html>
<head id="Head1" runat="server">
<title>Post Cache Substitution</title>
</head>
<body>
<form id="form1" runat="server">
    
Welcome <asp:Substitution 
ID="Substitution1" 
MethodName="DisplayUsername" 
Runat="Server" />!
    
<p>
此頁已緩存, 因?yàn)闀r(shí)間
<%= DateTime.Now.ToString("t") %> 并無改變。
</p>
       
</form>
</body>
</html>

Substitution 控件有一個(gè)非常重要的屬性:即 MethodName 屬性。MethodName 屬性用于表示為返回動(dòng)態(tài)內(nèi)容而調(diào)用的方法。由 Substitution 控件調(diào)用的方法必須是靜態(tài)方法(在 Visual Basic .NET 中共享的方法)。此外,該方法還必須具有一個(gè)表示當(dāng)前 HttpContext 的參數(shù)。

在 ASP.NET 2.0 Framework 中,已對 AdRotator 控件進(jìn)行了修改以支持 Post-Cache Substitution。如果在使用 OutputCache 指令的頁面中添加 AdRotator 控件,AdRotator 控件將自動(dòng)從其包含頁面的緩存策略中排除出去。

 

結(jié)論

緩存對由數(shù)據(jù)庫驅(qū)動(dòng)的 Web 應(yīng)用程序的性能具有非常大的影響。幸運(yùn)的是,ASP.NET 2.0 Framework 提供了許多新的重要增強(qiáng)功能,使您可以在應(yīng)用程序中更輕松地使用緩存功能。

新增的 DataSource 控件中包含的屬性使得在內(nèi)存中緩存數(shù)據(jù)庫數(shù)據(jù)變得非常容易。通過使用 DataSource 控件,您可以檢索并緩存數(shù)據(jù)庫數(shù)據(jù),而無需編寫任何代碼。

新增的 SQL Cache Invalidation 支持使您可以在基礎(chǔ)數(shù)據(jù)庫中的數(shù)據(jù)發(fā)生更改時(shí)自動(dòng)在緩存中重新加載數(shù)據(jù)庫數(shù)據(jù)。此功能為您提供了緩存的所有性能優(yōu)勢,而不用擔(dān)心數(shù)據(jù)過期的問題。

最后,使用新增的 Substitution 控件,您可以更輕松地在緩存的頁面中混合動(dòng)態(tài)內(nèi)容。Substitution 控件為您在緩存的頁面中插入動(dòng)態(tài)內(nèi)容提供了一個(gè)獨(dú)立的空間。

參考資料

ASP.NET Unleashed

A First Look at ASP.NET V. 2.0

ASP.NET 2.0 Revealed

作者簡介

Stephen Walther 編寫了有關(guān) ASP.NET 的暢銷書 ASP.NET Unleashed。此外,他還是 ASP.NET Community Starter Kit(Microsoft 開發(fā)的 ASP.NET 示例應(yīng)用程序)的體系結(jié)構(gòu)設(shè)計(jì)師和主要開發(fā)人員。他還通過自己的公司 Superexpert (http://www.superexpert.com/) 為美國的公司(包括 NASA 和 Microsoft)提供 ASP.NET 培訓(xùn)。

關(guān)鍵詞:ASP.NET