SqlServer缓存依赖实例
程序员文章站
2024-02-23 00:02:52
...
SqlServer缓存依赖
目的 :
- 字典表等数据变动不频繁,但使用率高的需要加入缓存.
- 当数据有变动时候,允许用户实时获取新数据.
- 注意缓存的数据量,避免内存溢出.
通过缓存依赖实现:
缓存依赖能够在数据库的内容发生改变时,及时通知缓存,并更新缓存中的数据
数据缓存依赖有两种实现模式,轮询模式和通知模式。
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>
上一篇: 【SqlServer】存储过程使用
下一篇: Linux下使用SQLServer