65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 缓存依赖

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.26/5 (21投票s)

2006年7月28日

6分钟阅读

viewsIcon

166624

downloadIcon

1816

关于 ASP.NET 2.0 中缓存的讨论

引言

缓存的概念在 ASP.NET 1.X 中就已经引入,并在 ASP.NET 2.0 中得到了显著改进。缓存允许您将常用项存储在内存中,从而在请求它们时不必从头开始创建。 .NET Framework 中有不同类型的缓存。在本文中,我将向您介绍缓存依赖项。

缓存依赖

缓存可以依赖于多个项,包括用户请求、文件、数据库表、表行、持续时间、用户控件、查询字符串、浏览器以及其他缓存项。让我们从缓存依赖于其他缓存项开始。

对缓存项的缓存依赖

值得注意的是,您的缓存项可以依赖于其他缓存项。这意味着如果从缓存中移除了项 A,您也可以从缓存中移除项 B。让我们首先在 Cache 对象中创建并插入项 A 和项 B。

protected void Button3_Click(object sender, EventArgs e)
{
    // create item A and item B
    string itemA = "ItemA";
    string itemB = "ItemB";
    Cache.Insert("ItemA", itemA, null, DateTime.Now.AddMinutes(10), 
    TimeSpan.Zero,
    CacheItemPriority.Default, MyItemRemovedCallBack);
    Cache.Insert("ItemB", itemB, null, DateTime.Now.AddMinutes(10), 
    TimeSpan.Zero,
    CacheItemPriority.Default, MyItemRemovedCallBack);
}

在上面的代码中,我创建了两个项“itemA”和“itemB”。创建项后,我只需使用 Insert 方法将这些项放入 Cache 对象。最后一个参数是回调方法“MyItemRemovedCallBack”,当其中任何一个项从缓存中移除时,它将被触发。

在回调方法中插入项到缓存中不是一个好主意,因为您可能不会立即需要该项,因此您将浪费宝贵的资源来创建它们。

让我们看一下 MyItemRemovedCallBack 的实现。

private void MyItemRemovedCallBack(string key, object value,
                   CacheItemRemovedReason reason)
{
    // remove the item from the cache
    if (key == "ItemA" ) Cache.Remove("ItemB");
    else if (key.Equals == "ItemB") Cache.Remove("ItemB");
}

MyItemRemovedCallBack 方法接受三个参数。

  1. key:用于在缓存中标识项的键。
  2. value:插入到缓存中的项的值。
  3. reason:“reason”变量是 CacheItemRemovedReason 枚举类型,它标识了项被从缓存中移除的原因。

下面的代码会从缓存中移除一个项,一旦该项被移除,“MyItemRemovedCallBack”方法就会被触发并移除缓存中的另一个项。

protected void Btn_RemoveCacheItem(object sender, EventArgs e)
{
    Cache.Remove("ItemA");
}

对文件的缓存依赖

接下来,让我们看一下缓存对文件的依赖。使缓存依赖于文件意味着当文件内容更改时,缓存会过期并重新获取内容。看看下面包含网站菜单信息的简单 XML 文件。

<?xml version="1.0" encoding="utf-8"?>
<MenuItems>
    <MenuItem>
        <Text>Home</Text>
    </MenuItem>
    <MenuItem>
        <Text>About us</Text>
    </MenuItem>
    <MenuItem>
        <Text>Contact us</Text>
    </MenuItem>
    <MenuItem>
        <Text>Help</Text>
    </MenuItem>
    <MenuItem>
        <Text>Feature</Text>
    </MenuItem>
</MenuItems>

我们将使用 Cache.Insert 方法使缓存依赖于文件。看看下面的代码

private void CreateMenu()
{
    string menuPath = "MyFiles/Menu.xml";
    string folderName = "MyFiles/";

    DataSet ds = null;
    if (Cache["Menu"] == null) 

我们将使用 Cache.Insert 方法使缓存依赖于文件。看看下面的代码

private void CreateMenu()
{
    string menuPath = "MyFiles/Menu.xml";
    string folderName = "MyFiles/";

    DataSet ds = null;
    if (Cache["Menu"] == null)
    {
        ds = new DataSet();
        ds.ReadXml(Server.MapPath(menuPath));

        // menu is created
        Cache.Insert("Menu", ds, new System.Web.Caching.CacheDependency(
            Server.MapPath(menuPath)),DateTime.Now.AddMinutes(60),
            TimeSpan.Zero,
            System.Web.Caching.CacheItemPriority.Default,
            new System.Web.Caching.CacheItemRemovedCallback(
                                  CacheItemRemovedCallBack));

       DisplayCacheCreationTime("Object was not in the cache and created at:",
             DateTime.Now.ToLongTimeString());
    }
    else
    {
        // menu is created from the cache
        DisplayCacheCreationTime("Object was in the cache",String.Empty);
    }
}

CreateMenu 方法负责创建缓存对文件的依赖。正如您所看到的,我使用了 DataSetReadXML 方法从 XML 文件中读取内容,然后将 DataSet 插入到缓存中。CacheDependency 方法负责设置缓存对文件的依赖。我还包含了一个 ItemRemovedCallBack 回调方法,当缓存依赖过期(在本例中是文件更改时)就会被触发。如果您第一次执行上面的代码,CreateMenu 方法会被执行,它会从文件读取内容,因为最初缓存是空的,但对于所有后续的请求,内容都是从缓存对象中获取的。

您还可以创建对文件夹的缓存依赖。这意味着当任何文件或子文件夹被添加或删除时,缓存就会过期并获取一个新的(最新的)副本。

对 SQL 的缓存依赖

ASP.NET 2.0 缓存最大的改进之一是缓存对数据库表的依赖功能。这意味着只要表中的条目不发生变化,数据就会保留在缓存中。一旦数据库表发生更改,缓存就会过期。您可以使用 aspnet_regsql.exe 命令行工具启用 SQL 缓存依赖。只需在 Visual Studio.NET 2005 命令行中键入以下命令:

aspnet_regsql -ed -E -d School

上面的命令将启用对“School”数据库的缓存依赖。下一步是启用对单个表的缓存。您可以通过使用以下行来完成:

aspnet_regsql -et -E -d School -t Users

上面的行将启用对 School 数据库中包含的 Users 表的缓存。

下一步是在 connectionStrings 部分创建 connectionString,并在 web.config 文件中创建 sqlCacheDependency。看看下面的代码

<connectionStrings>
    <add name="ConnectionString"
         connectionString="Server=localhost;Database=School;
Trusted_Connection=true"/>
</connectionStrings>

<system.web>
    <caching>
        <sqlCacheDependency pollTime="10000" enabled="true" >
            <databases>
                <add connectionStringName="ConnectionString" name="School"/>
            </databases>
        </sqlCacheDependency>
    </caching>lt;/caching>

正如您所注意到的,sqlCacheDependency 有一个 pollTime 属性,设置为“1000”毫秒。这意味着 ASP.NET 将每 10 秒检查一次数据库表是否有任何更改。<caching> 的数据库部分包含用于连接到数据库的 connectionString

最后一步是在您的代码中使用缓存。您可以通过多种方式进行。看看下面使用编程方式缓存的代码:

private void BindData()
{
    // if null then fetch from the database
    if (Cache["Users"] == null)
    {
        // Create the cache dependency
        SqlCacheDependency dep = new SqlCacheDependency("School", "Users");
        string connectionString = ConfigurationManager.ConnectionStrings[
                                        "ConnectionString"].ConnectionString;
        SqlConnection myConnection = new SqlConnection(connectionString);
        SqlDataAdapter ad = new SqlDataAdapter("SELECT FirstName, LastName " +
                                               "FROM Users", myConnection);
        DataSet ds = new DataSet();
        ad.Fill(ds);

        // put in the cache object
        Cache.Insert("Users", ds, dep);
    }

    gvUsers.DataSource = Cache["Users"] as DataSet;
    gvUsers.DataBind();
}

SqlCacheDependency dep = new SqlCacheDependency("School", "Users"); 这行代码用于在 School 数据库和 Users 表上创建缓存。在 BindData 方法的开头,我检查项是否已在缓存中。如果已在,我只需通过从 Cache 对象进行转换将其作为调用者返回。如果项不在 Cache 中,则从数据库获取数据并将其插入 Cache 对象。只要您更改数据库表“Users”中的任何内容,Cache 就会被丢弃。这意味着如果您在 Users 表中的任何行中执行 INSERTDELETEUPDATE 操作,Cache 将被视为过时,并会从数据库中获取最新数据的副本。

SQL Server 2005 中的缓存与 SQL Server 2000 中的缓存具有不同的架构。您无需在 web.config 中编写任何行即可在 SQL Server 2005 中启用缓存。此外,在 SQL Server 2005 中,只有当数据库表中的行发生更改时,Cache 才会过期。

结论

正确实现的缓存可以显著提高应用程序的性能。缓存还有很多内容需要学习,我将在我未来的文章中介绍。

希望您喜欢这篇文章,祝您编码愉快!

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.