zoukankan      html  css  js  c++  java
  • 系统缓存全解析6:数据库缓存依赖

    更多的时候,我们的服务器性能损耗还是在查询数据库的时候,所以对数据库的缓存还是显得特别重要,上面几种方式都可以实现部分数据缓存功能。但问题是我们的数据有时候是在变化的,这样用户可能在缓存期间查询的数据就是老的数据,从而导致数据的不一致。那有没有办法做到,数据如果不变化,用户就一直从缓存中取数据,一旦数据变化,系统能自动更新缓存中的数据,从而让用户得到更好的用户体验。

    答案是肯定的!.NET已经为我们提供了这样一种非常好的解决方法:SqlCacheDependency数据库缓存依赖。



    实现步骤:

    下面就让我们看一下如何实现数据库缓存依赖功能:

    第一步: 修改web.config,让项目启用SqlCacheDependency 。

    将下列代码加入web.config的<system.web>节:
    <?xml version="1.0"?>

    <configuration>

    <appSettings/>

    <connectionStrings>

    <add name="strcodematic" connectionString="data source=127.0.0.1;initial catalog=codematic;user id=sa;password=" providerName="System.Data.SqlClient" />

    </connectionStrings>

    <system.web>

    <caching>

    <sqlCacheDependency enabled="true" pollTime="6000">

    <databases>

    <add name="codematic" connectionStringName="strcodematic" />

    </databases>

    </sqlCacheDependency>

    </caching>



    <compilation debug="true">

    </compilation>

    <authentication mode="Windows"/>

    </system.web>

    </configuration>






    这里的connectionStringName指定了在<connectionStrings>中添加的某一个连接字符串。name则是为该SqlCacheDependency起的名字,这个名字将在第3步中用到。
    SqlCacheDependency类会自动完成对此配置节信息的读取以建立和数据库之间的联系。


    注意:

    在<databases>节的<add name="codematic" connectionStringName="strcodematic" />中的name属性值必须和第三步的Page_Load代码中System.Web.Caching.SqlCacheDependency("codematic", "P_Product"); 中的第一个参数(数据库名称)相一致。





    第二步:执行下述命令,为 数据库启用缓存依赖。

    如果要配置SqlCacheDependency,则需要以命令行的方式执行。

    aspnet_regsql.exe工具位于Windows\Microsoft.NET\Framework\[版本]文件夹中。

    aspnet_regsql -C "data source=127.0.0.1;initial catalog=codematic;user id=sa;password=" -ed -et -t "P_Product"

    参数-C后面的字符串是连接字符串(请替换成自己所需要的值),

    参数-t后面的字符串是数据表的名字。



    运行结果如图15-3所示:






    图15-3 启用数据库缓存依赖

    命令执行后,在指定的数据库中会多出一个AspNet_SqlCacheTablesForChangeNotification表。


    注意:

    要使得7.0或者2000版本以上的SQLServer支持SqlCacheDependency特性,需要对数据库服务器执行相关的配置。

    有两种方法配置SQLServer:

    一 使用aspnet_regsql命令行工具,

    二 使用SqlCacheDependencyAdmin类。



    例如:

    aspnet_regsql -S "server" -E -d "database" –ed 或者

    aspnet_regsql -S "server" -E -d "database" -et -t "table"
    如果是Sql验证的话要把-E换成,-U (用户名),-P (密码)



    以下是该工具的命令参数说明:

    -? 显示该工具的帮助功能;

    -S 后接的参数为数据库服务器的名称或者IP地址;

    -U 后接的参数为数据库的登陆用户名;

    -P 后接的参数为数据库的登陆密码;

    -E 使用当前登录用户的 Windows 集成认证进行身份验证。

    -d 后接参数为对哪一个数据库采用SqlCacheDependency功能;

    -C 连接数据库的连接字符串。如果您指定服务器(-S)和登录(-U和-P,或 -E)信息,则此选项不是必需的,因为连接字符串已经包含这些信息。

    -t 后接参数为对哪一个表采用SqlCacheDependency功能;

    -ed 允许对数据库使用SqlCacheDependency功能;

    -dd 禁止对数据库采用SqlCacheDependency功能;

    -et 允许对数据表采用SqlCacheDependency功能;

    -dt 禁止对数据表采用SqlCacheDependency功能;

    -lt 列出当前数据库中有哪些表已经采用sqlcachedependency功能。





    第三步:在代码中使用缓存,并为其设置SqlCacheDependency依赖:


    /// <summary>

    /// 获取当前应用程序指定CacheKey的Cache对象值

    /// </summary>

    /// <param name="CacheKey">索引键值</param>

    /// <returns>返回缓存对象</returns>

    public static object GetCache(string CacheKey)

    {

    System.Web.Caching.Cache objCache = HttpRuntime.Cache;

    return objCache[CacheKey];

    }

    /// <summary>

    /// 设置以缓存依赖的方式缓存数据

    /// </summary>

    /// <param name="CacheKey">索引键值</param>

    /// <param name="objObject">缓存对象</param>

    /// <param name="cacheDepen">依赖对象</param>

    public static void SetCache(string CacheKey, object objObject, System.Web.Caching.CacheDependency dep)

    {

    System.Web.Caching.Cache objCache = HttpRuntime.Cache;

    objCache.Insert(

    CacheKey,

    objObject,

    dep,

    System.Web.Caching.Cache.NoAbsoluteExpiration,//从不过期

    System.Web.Caching.Cache.NoSlidingExpiration,//禁用可调过期

    System.Web.Caching.CacheItemPriority.Default,

    null);

    }

    protected void Page_Load(object sender, EventArgs e)

    {

    string CacheKey = "cachetest";

    object objModel = GetCache(CacheKey);//从缓存中获取

    if (objModel == null)//缓存里没有

    {

    objModel = GetData();//把当前时间进行缓存

    if (objModel != null)

    {

    //依赖数据库codematic中的P_Product表变化 来更新缓存

    System.Web.Caching.SqlCacheDependency dep = new System.Web.Caching.SqlCacheDependency("codematic", "P_Product");

    SetCache(CacheKey, objModel, dep);//写入缓存

    }

    }



    GridView1.DataSource = (DataSet)objModel;

    GridView1.DataBind();

    }



    //查询数据

    private DataSet GetData()

    {

    string conString = "data source=127.0.0.1;initial catalog=codematic;user id=sa;password=";

    string strSQL = "SELECT * FROM P_Product";

    SqlConnection myConnection = new SqlConnection(conString);

    DataSet ds = new DataSet();

    myConnection.Open();

    SqlDataAdapter adapter = new SqlDataAdapter(strSQL, myConnection);

    adapter.Fill(ds, "Product");

    myConnection.Close();

    return ds;

    }






    从以上代码可以看出,和文件依赖基本相同,只是在存放缓存SetCache时存入的依赖对象不同罢了。这里用的是SqlCacheDependency。

    其中,创建SqlCacheDependency的构造方法:
    public SqlCacheDependency (string databaseEntryName,string tableName)




    l databaseEntryName :是在Web.config 文件的 caching 节的 sqlCacheDependency 的 databases 元素中定义的数据库的名称。

    l tableName :与 SqlCacheDependency 关联的数据库表的名称。

    这样,只有当P_Product表的内容发生变化时,查询操作才会重新查询数据更新缓存的内容,可以大大减少数据库的重复查询和提高系统的性能和运行效率。

    注意:上文说的数据库依赖都只是针对一张表的时候,当你要涉及到多张表的时候需要用到AggregateCacheDependency

    具体用法如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data;
    using System.Data.SqlClient;
    using System.Web.Caching;
    
    namespace YJUI.UI
    {
        /// <summary>
        /// 
        /// </summary>
        public partial class WebForm1 : System.Web.UI.Page
        {
    
    
            /// <summary>
    
            /// 获取当前应用程序指定CacheKey的Cache对象值
    
            /// </summary>
    
            /// <param name="CacheKey">索引键值</param>
    
            /// <returns>返回缓存对象</returns>
    
            public static object GetCache(string CacheKey)
            {
    
                System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    
                return objCache[CacheKey];
    
            }
    
            /// <summary>
    
            /// 设置以缓存依赖的方式缓存数据
    
            /// </summary>
    
            /// <param name="CacheKey">索引键值</param>
    
            /// <param name="objObject">缓存对象</param>
    
            /// <param name="cacheDepen">依赖对象</param>
    
            public static void SetCache(string CacheKey, object objObject, System.Web.Caching.CacheDependency dep)
            {
    
                System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    
                objCache.Insert(
    
                    CacheKey,
    
                    objObject,
    
                    dep,
    
                    System.Web.Caching.Cache.NoAbsoluteExpiration,//从不过期
    
                    System.Web.Caching.Cache.NoSlidingExpiration,//禁用可调过期
    
                    System.Web.Caching.CacheItemPriority.Default,
    
                    null);
    
            }
    
            protected void Page_Load(object sender, EventArgs e)
            {
                DateTime a = DateTime.Now;
                string CacheKey = "cachetest";
    
                object objModel = GetCache(CacheKey);//从缓存中获取
    
                if (objModel == null)//缓存里没有
                {
    
                    objModel = GetData();//把当前时间进行缓存
    
                    if (objModel != null)
                    {
                        AggregateCacheDependency dependency = new AggregateCacheDependency(); 
                        //依赖数据库codematic中的P_Product表变化 来更新缓存
    
                        System.Web.Caching.SqlCacheDependency dep = new System.Web.Caching.SqlCacheDependency("YJUIDB", "ui_user");
                        System.Web.Caching.SqlCacheDependency dep2 = new System.Web.Caching.SqlCacheDependency("YJUIDB", "ui_user_role");
                        dependency.Add(dep);
                        dependency.Add(dep2);
                        SetCache(CacheKey, objModel, dependency);//写入缓存
    
                    }
    
                }
                gridview_dpList.DataSource = (DataSet)objModel;
    
                gridview_dpList.DataBind();
                DateTime b = DateTime.Now;
    
    
            }
    
    
    
            //查询数据
    
            private DataSet GetData()
            {
    
                string conString = "Data Source=THANKPAD-SZGL;Initial Catalog=YJUIDB;User ID=sa;Password=123456";
    
                string strSQL = "SELECT a.*,b.ui_role_id FROM dbo.ui_user a JOIN dbo.ui_user_role b ON a.id=b.ui_user_id";
    
                SqlConnection myConnection = new SqlConnection(conString);
    
                DataSet ds = new DataSet();
    
                myConnection.Open();
    
                SqlDataAdapter adapter = new SqlDataAdapter(strSQL, myConnection);
    
                adapter.Fill(ds, "Product");
    
                myConnection.Close();
    
                return ds;
    
            }
        }
    }
  • 相关阅读:
    系统调用与库函数
    在树莓派上 搭建sqlite数据库
    (转)inux Read系统调用
    查看当前日期是这一年的第几天
    求解某个范围内的全部完数
    求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。
    输入三个整数x,y,z,请把这三个数据由大到小输出。
    模仿ArrayList底层实现
    可视化日历
    Oracle之约束条件1:主键约束
  • 原文地址:https://www.cnblogs.com/wenghaowen/p/3269799.html
Copyright © 2011-2022 走看看