演练:在 ASP.NET 中缓存应用程序数据

缓存使您能够在内存中存储数据以实现快速访问。 应用程序无论何时访问数据,都可以访问缓存,而不必从原始源检索数据。 这样可以避免重复查询数据,也可以改进性能和伸缩性。 此外,缓存还使数据在数据源临时不可用时可用。

.NET Framework 提供的类使您能够在 ASP.NET 应用程序中使用缓存功能。 这些类是在 System.Runtime.Caching 命名空间中定义的。

备注

System.Runtime.Caching 命名空间是 .NET Framework 4 中新增的命名空间。此命名空间使缓存对所有的 .NET Framework 应用程序可用。

本演练演示如何作为 ASP.NET 应用程序的一部分,使用 .NET Framework 中提供的缓存功能。 在本演练中,您将缓存文本文件的内容。

本演练演示以下任务:

  • 创建 ASP.NET 网站。

  • 添加对 .NET Framework 4 的引用。

  • 添加缓存文件内容的缓存项。

  • 为缓存项提供逐出策略。

  • 监视缓存文件的路径,并向缓存通知被监视项的更改情况。

系统必备

若要完成本演练,您需要:

  • Microsoft Visual Studio 2010。

  • 包含少量文本的文本文件。 您将在网页中显示此文本文件的内容。

创建 ASP.NET 网站

首先将创建一个 ASP.NET 网站。

警告

本演练使用网站项目。您可以改用 Web 应用程序项目。有关这些 Web 项目类型之间的差异的信息,请参见 Web 应用程序项目与网站项目

创建 ASP.NET 网站

  1. 启动 Visual Studio 2010。

  2. 在**“文件”菜单中单击“新建网站”。 (如果看不到此选项,请单击“新建”,然后单击“网站”**。)

    将显示**“新建网站”**对话框。

  3. 在**“已安装的模板”下,单击“Visual Basic”“C#”,然后选择“ASP.NET 网站”**。

  4. 在**“Web 位置”框中选择“文件系统”,然后输入要在其中保存网站页面的文件夹的名称。 例如,输入文件夹名称 C:\Websites\AppCaching,然后单击“确定”**。

    Visual Studio 将创建一个包含预置功能的 Web 项目,这些功能面向布局(母版页、Default.aspx 和 About.aspx 内容页以及级联样式表)、Ajax(客户端脚本文件)和身份验证(ASP.NET 成员资格)。 默认情况下,在创建新页后,Visual Web Developer 会在**“源”**视图中显示该页,您可以在此视图中查看该页的 HTML 元素。

下一步是将要使用的文本文件添加到当前网站项目。

向项目中添加文本文件

  1. 在**“解决方案资源管理器”中,右击项目名称,然后单击“添加现有项”**。

  2. 在**“添加现有项”对话框中,选择您想要用于本演练的文本文件,然后单击“添加”**。

添加对缓存程序集的引用

若要在 ASP.NET 应用程序中使用 System.Runtime.Caching 命名空间,则必须添加对该命名空间的引用。

添加对网站的引用

  1. 在**“解决方案资源管理器”中,右击网站的名称,然后单击“添加引用”**。

  2. 选择**“.NET”选项卡,选择“System.Runtime.Caching”,然后单击“确定”**。

向 ASP.NET 页添加控件

下一步是向此页中添加一个按钮和一个 Label 控件。 为按钮的 Click 事件创建事件处理程序。 稍后将添加代码,以便在您单击按钮时,缓存的文本会显示在 Label 控件中。

将控件添加到页

  1. 打开或切换到 Default.aspx 页。

  2. 从**“工具箱”“标准”**选项卡,将一个 Button 控件拖到 Default.aspx 页上。

  3. 在**“属性”**窗口中,将 Button 控件的 Text 属性设置为“Get From Cache”。 接受默认 ID 属性。

  4. 从**“工具箱”“标准”**选项卡,将 Label 控件拖动到页面上。 接受默认 ID 属性。

创建缓存并缓存项

接下来,您将添加代码来执行以下任务:

  • 创建一个缓存类实例,即,您将实例化缓存对象。

  • 指定缓存将使用 HostFileChangeMonitor 对象来监视文本文件中的更改。

  • 读取文本文件并将其内容缓存为缓存项。

  • 显示缓存文本文件的内容。

创建缓存对象

  1. 双击按钮将在 Default.aspx.cs 或 Default.aspx.vb 文件中创建一个事件处理程序。

  2. 在文件的顶部(在类声明前面),添加以下 Imports (Visual Basic) 或 using (C#) 语句。

    [Visual Basic]

    Imports System.Runtime.Caching
    Imports System.IO
    

    [C#]

    using System.Runtime.Caching;
    using System.IO;
    
  3. 在事件处理程序中,添加以下代码以实例化缓存。

    [Visual Basic]

    Dim cache As ObjectCache = MemoryCache.Default
    

    [C#]

    ObjectCache cache = MemoryCache.Default;
    

    ObjectCache 是一个基类,提供用于实现在内存中缓存对象的方法。

    备注

    在 ASP.NET 4 中,通过使用 ObjectCache 类来实现缓存。

  4. 添加以下代码,以读取名为 filecontents 的缓存项的内容。

    [Visual Basic]

    Dim fileContents As String = TryCast(cache("filecontents"), String)
    

    [C#]

    string fileContents = cache["filecontents"] as string;
    
  5. 添加以下代码,以检查是否存在名为 filecontents 的缓存项。

    [Visual Basic]

    If fileContents Is Nothing Then
    
    End If
    

    [C#]

    if (fileContents == null)
    {
    
    }
    

    如果指定的缓存项不存在,则您必须读取该文本文件并将其作为一个缓存项添加到缓存。

  6. 在 if/then 块中,添加以下代码,以创建一个新的 CacheItemPolicy 对象,该对象指定缓存将在 10 秒后过期。

    [Visual Basic]

    Dim policy As New CacheItemPolicy()
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0)
    

    [C#]

    CacheItemPolicy policy = new CacheItemPolicy();
    policy.AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10.0);
    

    如果未提供任何逐出或过期信息,则默认值为 InfiniteAbsoluteExpiration,这意味着缓存中的项不会基于绝对过期时间而过期。 相反,项仅当存在内存压力时才过期。 最佳做法是,您应始终明确提供一个绝对过期或可调过期。 在本演练中,使用的绝对过期时间为 10 秒钟。

  7. 在 if/then 块内部,在上一步中所添加的代码后面,添加以下代码,以便为要监视的文件路径创建一个集合,并向该集合中添加文本文件的路径。

    [Visual Basic]

    Dim filePaths As New List(Of String)()
    Dim cachedFilePath As String = Server.MapPath("~") & _
            "\cacheText.txt"
    filePaths.Add(cachedFilePath)
    

    [C#]

    List<string> filePaths = new List<string>();
    string cachedFilePath = Server.MapPath("~") + "\\cacheText.txt";
    filePaths.Add(cachedFilePath);
    

    HttpServerUtilityMapPath() 方法将返回指向当前网站的根的路径。

  8. 在上一步中所添加的代码后面,添加以下代码,以便将新的 HostFileChangeMonitor 对象添加到缓存项的更改监视集合。

    [Visual Basic]

    policy.ChangeMonitors.Add(New HostFileChangeMonitor(filePaths))
    

    [C#]

    policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));
    

HostFileChangeMonitor 对象将监视文本文件的路径并向缓存通知是否发生更改。 在此示例中,如果文件的内容发生更改,则缓存项将自动过期。

  1. 在上一步中所添加的代码后面,添加以下代码,以读取文本文件的内容。

    fileContents = File.ReadAllText(cachedFilePath) & vbCrLf & DateTime.Now.ToString()
    
    fileContents = File.ReadAllText(cachedFilePath) + "\n" + DateTime.Now; 
    

    添加日期和时间戳,以帮助您确定缓存项何时过期。

  2. 在上一步中所添加的代码后面,添加以下代码,以将文件内容作为 CacheItem 实例插入到缓存对象。

    [Visual Basic]

    cache.Set("filecontents", fileContents, policy)
    

    [C#]

    cache.Set("filecontents", fileContents, policy);
    

    通过将 CacheItemPolicy 对象作为参数传递给 Set 方法,指定有关应如何逐出缓存项的信息。

  3. 在 if/then 块后面,添加以下代码,以便在 Label 控件中显示缓存的文件内容。

    [Visual Basic]

    Label1.Text = fileContents
    

    [C#]

    Label1.Text = fileContents;
    

在 ASP.NET 网站中测试缓存

您现在可以测试应用程序。

在 ASP.NET 网站中测试缓存

  1. 按 Ctrl+F5 以运行应用程序。

  2. 单击**“Get From Cache”**。

    在标签中显示文本文件中的缓存内容。 注意文件末尾的时间戳。

  3. 再次单击**“Get From Cache”**。

    时间戳未更改。 这将指示显示缓存的内容。

  4. 等待 10 秒或更长时间之后,再次单击**“Get From Cache”**。

    这次将显示一个新的时间戳。 这指示策略让缓存在 10 秒后过期,并显示新缓存的内容。

  5. 在文本编辑器中,打开您添加到网站项目的文本文件。 不要进行任何更改。

  6. 再次单击**“Get From Cache”**。

    再次注意时间戳。

  7. 对文本文件进行更改,然后保存文件。

  8. 再次单击**“Get From Cache”**。

    这次时间戳将立即更改。 这指示主机文件更改监视器在您做出更改时立即逐出了缓存项。

    备注

    您可将逐出时间提高到 20 秒或更长,以允许您在文件中进行更长时间的更改。

代码示例

完成本演练后,您创建的网站的代码将与下面的示例类似。

Imports System.Runtime.Caching
Imports System.IO

Partial Class _Default
    Inherits System.Web.UI.Page

    Protected Sub Button1_Click(ByVal sender As Object, _
            ByVal e As System.EventArgs) Handles Button1.Click
        Dim cache As ObjectCache = MemoryCache.Default
        Dim fileContents As String = TryCast(cache("filecontents"), _
            String)
        If fileContents Is Nothing Then
            Dim policy As New CacheItemPolicy()
            policy.AbsoluteExpiration = _
                DateTimeOffset.Now.AddSeconds(10.0)
            Dim filePaths As New List(Of String)()
            Dim cachedFilePath As String = Server.MapPath("~") & _
                "\cacheText.txt"
            filePaths.Add(cachedFilePath)
            policy.ChangeMonitors.Add(New  _
                HostFileChangeMonitor(filePaths))

            ' Fetch the file contents.
            fileContents = File.ReadAllText(cachedFilePath) & _
                vbCrLf & DateTime.Now.ToString()
            cache.Set("filecontents", fileContents, policy)
        End If
        Label1.Text = fileContents
    End Sub

End Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Runtime.Caching;
using System.IO;

public partial class _Default : System.Web.UI.Page
{


    protected void Button1_Click1(object sender, EventArgs e)
    {
        ObjectCache cache = MemoryCache.Default;
        string fileContents = cache["filecontents"] as string;

        if (fileContents == null)
        {
            CacheItemPolicy policy = new CacheItemPolicy();
            policy.AbsoluteExpiration =
                DateTimeOffset.Now.AddSeconds(10.0);

            List<string> filePaths = new List<string>();
            string cachedFilePath = Server.MapPath("~") +
                "\\cacheText.txt";

            filePaths.Add(cachedFilePath);

            policy.ChangeMonitors.Add(new
                HostFileChangeMonitor(filePaths));

            // Fetch the file contents.
            fileContents = File.ReadAllText(cachedFilePath) + "\n"
                + DateTime.Now.ToString();

            cache.Set("filecontents", fileContents, policy);

        }

        Label1.Text = fileContents;
    }
}

后续步骤

在 ASP.NET 中,可以使用多个缓存实现来缓存数据。 有关更多信息,请参见 Caching Application Data by Using Multiple Cache Objects in an ASP.NET Application(通过在 ASP.NET 应用程序中使用多个缓存对象来缓存应用程序数据)。

请参见

参考

MemoryCache

ObjectCache

概念

.NET Framework 应用程序中的缓存