SqlServer缓存依赖实例

SqlServer缓存依赖

目的 :

  1. 字典表等数据变动不频繁,但使用率高的需要加入缓存.
  2. 当数据有变动时候,允许用户实时获取新数据.
  3. 注意缓存的数据量,避免内存溢出.

通过缓存依赖实现:

缓存依赖能够在数据库的内容发生改变时,及时通知缓存,并更新缓存中的数据

数据缓存依赖有两种实现模式,轮询模式和通知模式。

1 轮询模式实现步骤

​ 此模式需要SQL SERVER 7.0/2000/2005版本以上版本都支持

​ 不需要启用Service Broker

​ 需要在数据库中执行,或者在数据库右键属性,选项中修改ENABLE BROKER为true

1.1 使用aspnet_regsql命令行或SqlCacheDependencyAdmin来配置连接数据库
1.1.1 aspnet_regsql方式:

  • 在.Net Framework 2.0
    的安装目录下(通常是WINDOWS\Microsoft.NET\Framework\v2.0.XXXXX),有一个aspnet_regsql.exe,这个命令行工具可以帮助我们使数据库支持SqlCacheDependency特性

  • 首先:“aspnet_regsql –S 服务器名 –U 登陆名 ID –P 密码 –d 数据库名
    –ed”,这个命令使指定数据库支持SqlCacheDependency, 然后我们再加入要追踪的数据表:“aspnet_regsql
    –S 服务器名 –U 登陆名 ID –P 密码 –d 数据库名 –t 追踪的数据表
    –et”,这个命令使指定的Table支持SqlCacheDependency。

  • 轮询模式的实质,就是在指定的数据库中会新建一个Table,叫做“AspNet_SqlCacheTablesForChangeNotification”,这个表有三个字段,“tableName”记录要追踪的数据表的名称,“notificationCreated”记录开始追踪的时间,“changeId”是一个int类型的字段,每当追踪的数据表的数据发生变化时,这个字段的值就加1。

  • 它还会在指定的数据库中增加几个存储过程,用来让ASP.NET引擎查询追踪的数据表的情况。
    然后,它会给我们要追踪的Table加上几个Trigger,分别对应到Insert、Update、Delete操作,这几个Trigger的语句非常简单,就是把“AspNet_SqlCacheTablesForChangeNotification”表中对应“tableName”字段为这个追踪的表的名称的记录的“changeId”字段加上一个1。

  • ASP.NET引擎通过执行它加上的存储过程“AspNet_SqlCachePollingStoredProcedure”,这个存储过程直接返回“AspNet_SqlCacheTablesForChangeNotification”表的内容,让ASP.NET引擎知道哪个表的数据发生的变化。默认每500毫秒执行这个存储过程一次,不过可以在web.config里面修改这个间隔时间。
1.1.2 SqlCacheDependencyAdmin方式:

​ 也可以在Global.asax中 Application_Start 方法内加入以下代码

  var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["数据库名称"].ToString();
  //启动数据库的数据缓存依赖功能    
  SqlCacheDependencyAdmin.EnableNotifications(connectionString);
  //启用数据表缓存
  SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString, "表名称");
1.2 配置文件
<!-- KWS数据库连接信息 -->
<connectionStrings>
    <add name="Connection" connectionString="DataString"/>
</connectionStrings>
  
<!--在system.web节点下添加-->
<!--注意事项:配置中add name值为数据库名,与connectionStringName为连接数据库字段的名称要相同-->
<!--pollTime: 设置 SqlCacheDependency 轮询数据库表以查看是否发生更改的频率(以毫秒计算)-->
<caching>
  <sqlCacheDependency enabled="true" pollTime="1000">
     <databases>
       <add name="CacheData" connectionStringName="Connection" pollTime="1000"/>
     </databases>
  </sqlCacheDependency>
</caching>
2 通知模式实现步骤

​ SQL SERVER 2005(包括SQL SERVER 2005)以上的数据库才可以使用。

​ 需要启用Service Broker

​ 与轮询模式完全一致,但不用aspnet_regsql方式。

2.1 启动调用SqlDependency.Start(),结束时调用SqlDependency.Stop()

​ 推荐在Global.asax中 Application_Start Application_End 方法内加入代码.

        protected void Application_Start()
        {
            SqlDependency.Start(connectionString);
        }

        protected void Application_End()
        {
            SqlDependency.Stop(connectionString);
        }

​ 很明显通知模式,配置文件不需要任何特殊处理,数据库中也没有增加表AspNet_SqlCacheTablesForChangeNotification和Trigger,性能也比轮询模式好的多。只要数据库中数据有改变,cache中的对应数据就会清空,基本上是实时的,不像轮询模式由pollTime决定。

case:

1.在Global.asax全局配置文件中增加以下代码

 protected void Application_Start()
        {
            //启动数据库的数据缓存依赖功能   --使用轮询方式实现
            SqlCacheDependencyAdmin.EnableNotifications(connectionString);
            //启用数据表缓存               --使用轮询方式实现 
            SqlCacheDependencyAdmin.EnableTableForNotifications(connectionString, "Employee");

            //开启通知模式                 --使用通知方式实现
            //SqlDependency.Start(connectionString);
        }

        protected void Application_End()
        {
            //关闭数据库的数据缓存依赖功能   --使用轮询方式实现
            SqlCacheDependencyAdmin.DisableNotifications(connectionString);
            //关闭数据表缓存               --使用轮询方式实现 
            SqlCacheDependencyAdmin.DisableTableForNotifications(connectionString, "Employee");

            //关闭通知模式                 --使用通知方式实现
            //SqlDependency.Stop(connectionString);
        }

2.在web.config文件中添加轮询模式的功能支持

	<!-- 数据库连接信息 -->
	<connectionStrings>
		<add name="DBconnection" connectionString="server=localhost;database=DB;Trusted_Connection=SSPI" providerName="System.Data.SqlClient"/>
	</connectionStrings>

  <system.web>
	  <!--在system.web节点下添加
	  注意事项:配置中add name值为数据库名,与connectionStringName为连接数据库字段的名称要相同
	  pollTime: 设置 SqlCacheDependency 轮询数据库表以查看是否发生更改的频率(以毫秒计算)-->
	  <caching>
		  <sqlCacheDependency enabled="true" pollTime="1000">
			  <databases>
				  <add name="sqlCacheData" connectionStringName="DBconnection" />
			  </databases>
		  </sqlCacheDependency>
	  </caching>
  </system.web>

3.创建一个实体类

 public class Employee
    {
        //数据库中对应创建好
        public int id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
    }

4.在Controller中新建两个action

 public ActionResult Index()
        {
            var Employees = new List<Employee>();
            var rs = HttpContext.Cache["employees"] as List<Employee>;
            //判断缓存中是否有数据
             if (rs == null)
            {
                using (var conn = new           SqlConnection(ConfigurationManager.ConnectionStrings["DBconnection"].ConnectionString))
                {
                    conn.Open();
                    rs = conn.Query<Employee>("select * from Employee").ToList();
                    //制定缓存策略 
                    //轮询模式实现
                    var scd = new SqlCacheDependency("sqlCacheData", "Employee");

                    //插入缓存
                    //HttpContext.Cache 只能应用在WEB
                    //DateTime.Now.AddSeconds(10)表示缓存在10秒后过期,TimeSpan.Zero表示不使用平滑过期策略。
                    //DateTime.MaxValue表示不使用绝对时间过期策略,TimeSpan.FromSeconds(10)表示缓存连续10秒没有访问就过期。
                    HttpRuntime.Cache.Insert("employees", rs, scd);
                    ViewBag.DataFromMsg = "数据来源--DB";
                    return View(rs);
                }
            }
            else
                ViewBag.DataFromMsg = "数据来源--HttpRuntime.Cache";
            return View(HttpContext.Cache["employees"] as List<Employee>);


        }


        public ActionResult About()
        {
            var Employees = new List<Employee>();
            var rs = HttpContext.Cache["employees"] as List<Employee>;
            //判断缓存中是否有数据
            if (rs == null)
            {
                using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DBconnection"].ConnectionString))
                {
                    conn.Open();
                    SqlCommand sqlCmd = new SqlCommand("select id as id,name as Name,age as Age from dbo.Employee", conn);
                    //制定缓存策略
                    //通知模式实现,不需要配置web.config
                    var scdd = new SqlDependency(sqlCmd);
                    scdd.OnChange += new OnChangeEventHandler(dependency_OnChange);
                    SqlDataAdapter sda = new SqlDataAdapter(sqlCmd);
                    DataSet ds = new DataSet();
                    sda.Fill(ds);
                    foreach (DataRow mDr in ds.Tables[0].Rows)
                    {
                        Employees.Add(new Employee()
                        {
                            id = int.Parse(mDr["id"].ToString()),
                            Name = mDr["Name"].ToString(),
                            Age = int.Parse(mDr["Age"].ToString())
                        });
                    }
                    HttpRuntime.Cache.Insert("employees", Employees);
                }
                    rs = HttpContext.Cache["employees"] as List<Employee>;
                    ViewBag.DataFromMsg = "数据来源--DB";
                    return View(rs);
            }
            else
                 ViewBag.DataFromMsg = "数据来源--HttpRuntime.Cache";
            return View(rs);
        }
        //数据有变动就清空缓存
        public  void dependency_OnChange(object sender, SqlNotificationEventArgs e)
        {
           HttpContext.Cache.Remove("employees");
        }

5.页面输出

@using System.Web.Caching;
@using WebApplication.Models;

@model List<Employee>
@{
    ViewBag.Title = "Home Page";
}

<h1>@ViewBag.DataFromMsg</h1>

<table>
    <tr>
        <th>EID</th>
        <th>NAME</th>
        <th>Age</th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td >@item.id</td>
            <td >@item.Name</td>
            <td >@item.Age</td>
        </tr>
    }
</table>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值