欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SqlServer缓存依赖实例

程序员文章站 2024-02-23 00:02:52
...

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>

相关标签: C# sqlserver c#