缓存应用程序页面和数据(二)
 
一.使用DataSource缓存
    包括SqlDataSource、ObjectDataSource、XmlDataSource3个数据源控件。
1.优点:
l         可以在数据更新时自动重新载入数据;
l         可以在多个页面间共享相同的数据。比如,当两个SqlDataSource数据源控件的SelectCommand、SelectParameters和ConnectionString属性相同,则这两个控件将共享相同的缓存数据。
2.使用绝对过期策略(缺省)
    适用情形:数据的修改不频繁。
    示例:
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="true"
            DataKeyNames="CategoryID"
            DataSourceID="SqlDataSource1">
        </asp:GridView>
        <asp:SqlDataSource ID="SqlDataSource1"
            runat="server"
            ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
            SelectCommand="SELECT * FROM [Categories]"
            EnableCaching="True"
            CacheDuration="60"            
            OnSelecting="SqlDataSource1_Selecting">
        </asp:SqlDataSource>
3.使用相对过期策略
    适用情形:缓存的数据量比较大,或者数据频繁被修改。这样就可以缓存最常被访问的数据。
    方法:设置DataSource数据源控件的CacheExpirationPolicy="Sliding"
4.使用ObjectDataSource控件缓存
    ObjectDataSource控件支持和SqlDataSource控件一样的缓存属性。
    如果要在多个ObjectDataSource之间共享相同的数据,则它们的TypeName、SelectMethod和SelectParameters属性必须一样。
5.使用XmlDataSource控件缓存
    和前面两个数据源控件不一样,XmlDataSource控件默认情况下就启用了缓存功能。如果Xml文件被修改,则XmlDataSource控件自动重新载入修改过的Xml文件。
6.创建数据源控件键值依赖
    可以在数据源控件和应用程序中的一个缓存项目之间创建一个键值依赖。这样,如果缓存项目的值发生了更改,则所有依赖该缓存项目的数据源控件就会重新载入数据。
(1)DataSourceKeyDependency.aspx:
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="true"
            DataKeyNames="CategoryID"
            DataSourceID="SqlDataSource1">
        </asp:GridView>
        <asp:SqlDataSource ID="SqlDataSource1"
            runat="server"
            ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
            SelectCommand="SELECT * FROM [Categories]"
            EnableCaching="True"
            CacheDuration="60" 
            CacheExpirationPolicy="Sliding" 
            CacheKeyDependency="Category"        
            OnSelecting="SqlDataSource1_Selecting">
        </asp:SqlDataSource>
(2)Global.asax:
    void Application_Start(object sender, EventArgs e)
    {
        HttpContext.Current.Cache.Insert("Category",DateTime.Now,
            null,DateTime.MaxValue,
            Cache.NoSlidingExpiration,
            CacheItemPriority.NotRemovable,null);
    }
(3)AddCategoryDataSourceKeyDependency.aspx:(用于向类别表中插入一条记录)
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default3.aspx.cs" Inherits="Default3" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>添加类别信息</title>
</head>
<body>
    <form id="form1" runat="server">
        类别名称:<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox><br />
        类别描述:<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox><br />
        <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
    </form>
</body>
</html>
(4)AddCategoryDataSourceKeyDependency.aspx.cs:
    protected void Button1_Click(object sender, EventArgs e)
    {
        string strConn =
            WebConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
        string strSql = "insert into Categories(CategoryName,Description) values(@categoryName,@description)";
        SqlConnection cn = new SqlConnection(strConn);
        SqlCommand cm = new SqlCommand();
        cm.Connection = cn;
        cm.CommandText = strSql;
        cm.Parameters.AddWithValue("categoryName",TextBox1.Text);
        cm.Parameters.AddWithValue("description",TextBox2.Text);
        cn.Open();
        cm.ExecuteNonQuery();
        cn.Close();
        Cache.Insert("Category", DateTime.Now);
        Response.Redirect("Default2.aspx");
    }
   
当插入一条新的类别信息时,Category项目会重新插入到缓存中,此时,每一个依赖于这个键值的DataSource会自动重新载入数据。
二.使用数据缓存
    Cache对象。
    Cache对象是ASP.NET中所有缓存的根本机制。
    每一个ASP.NET应用程序,都会创建一个Cache对象的实例。
1.添加项目到缓存
    Insert()方法
    protected void Page_Load(object sender, EventArgs e)
    {
        DataTable dt = (DataTable)Cache["categories"];
        if (dt == null)
        {
            dt = GetCategories();
            Cache.Insert("categories", dt);
        }
        GridView1.DataSource = dt;
        GridView1.DataBind();
    }
    private DataTable GetCategories()
    {
        string strConn =
            WebConfigurationManager.
            ConnectionStrings["NorthwindConnectionString"].
            ConnectionString;
        string strSql = "select categoryID,categoryName from categories";
        SqlConnection cn = new SqlConnection(strConn);
        SqlDataAdapter da =
            new SqlDataAdapter(strSql,cn);
        DataTable dt = new DataTable();
        da.Fill(dt);
        return dt;
    }
2.使用绝对过期策略添加项目
    Cache.Insert("categories", dt,
        null,
        DateTime.Now.AddHours(1),
        Cache.NoSlidingExpiration);
3.使用相对过期策略添加项目
    Cache.Insert("categories",
        dt,
        null,
        Cache.NoAbsoluteExpiration,
        TimeSpan.FromMinutes(10));
4.使用依赖添加到项目
    当添加项目到Cache中时,可以让项目依赖一个外部对象。这样如果外部对象被修改,则项目自动从缓存中移除。
    ASP.NET2.0包括3种缓存依赖类:
l         CacheDependency:用于创建一个文件依赖或缓存键值依赖;
l         SqlCacheDependency:用于创建一个对SQL Server数据库查询的依赖;
l         AggregateCacheDependency:用于使用多个CacheDependency对象创建依赖。可以使用该对象组合文件和SQL依赖。
CacheDependency类是基类。其他两个类都从该类继承。
    现在,让我们将上述缓存到Cache中的项目依赖于category.txt文本文件。
(1)   基于Categories数据表创建一个触发器:
CREATE TRIGGER t
ON Categories
AFTER INSERT,UPDATE,DELETE
AS
DECLARE @v1 varchar(200)
DECLARE @v2 varchar(100)
SET @v1 = cast(datepart(year,getdate()) as varchar) +
    cast(datepart(month,getdate()) as varchar) +
    cast(datepart(day,getdate()) as varchar) +
    cast(datepart(hour,getdate()) as varchar) +
    cast(datepart(minute,getdate()) as varchar) +
    cast(datepart(second,getdate()) as varchar) +
    cast(datepart(ms,getdate()) as varchar)
SET @v2 = '@echo ' + @v1 + '>e:"prog"asp.net"Chapter16"Category.txt'
EXECUTE master..xp_cmdshell @v2
(2)   ShowCategory.aspx.cs
        DataTable dt = (DataTable)Cache["category"];
        if (dt == null)
        {
            string fileName = MapPath("~/Category.txt");
            CacheDependency dep =
                new CacheDependency(fileName);
            dt = GetCategories();
            Cache.Insert("category", dt,dep);
        }
        GridView1.DataSource = dt;
        GridView1.DataBind();
5.指定缓存项目优先级
    CacheItemPriority属性