主要用到 System.Runtime.Caching
框架自动给了一个默认值 MemoryCache.Default;
查看微软关于MemoryCache的介绍,可以看到它有Add、Get、Set 、 Contains 、Remove等几个方法, 也就是我们常用的了,比较简单
网上找了一段对这个封装的代码:
/// <summary>
/// Represents a MemoryCacheCache
/// </summary>
public static class CacheManager
{
public static ObjectCache Cache
{
get
{
return MemoryCache.Default;
}
}
public static bool Contains(string key)
{
return Cache.Contains(key);
}
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="key">The key of the value to get.</param>
/// <returns>The value associated with the specified key.</returns>
public static T Get<T>(string key)
{
return (T)Cache[key];
}
/// <summary>
/// Adds the specified key and object to the cache.
/// </summary>
/// <param name="key">key</param>
/// <param name="data">Data</param>
/// <param name="cacheTime">Cache time</param>
public static void Set(string key, object data, int cacheTime)
{
if (data == null)
return;
var policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
Cache.Set(new CacheItem(key, data), policy);
}/// <summary>
/// Gets a value indicating whether the value associated with the specified key is cached
/// </summary>
/// <param name="key">key</param>
/// <returns>Result</returns>
public static bool IsSet(string key)
{
return (Cache.Contains(key));
}
/// <summary>
/// Removes the value with the specified key from the cache
/// </summary>
/// <param name="key">/key</param>
public static void Remove(string key)
{
Cache.Remove(key);
}
/// <summary>
/// Removes items by pattern
/// </summary>
/// <param name="pattern">pattern</param>
public static void RemoveByPattern(string pattern)
{
var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);
var keysToRemove = new List<String>();
foreach (var item in Cache)
if (regex.IsMatch(item.Key))
keysToRemove.Add(item.Key);
foreach (string key in keysToRemove)
{
Remove(key);
}
}
/// <summary>
/// Clear all cache data
/// </summary>
public static void Clear()
{
foreach (var item in Cache)
Remove(item.Key);
}
框架提供了缓存的更新机制
查看MemoryCache的Add方法:Add(CacheItem, CacheItemPolicy)
其中的参数CacheItemPolicy有一个ChangeMonitors属性, 该属性可选项为
System.Runtime.Caching.CacheEntryChangeMonitor System.Runtime.Caching.FileChangeMonitor System.Runtime.Caching.SqlChangeMonitor
可以看出添加cache的时候可以设置此cache的几种类型的依赖
网上看到有FileChangeMonitor的例子, 现在小罗遇到的需求是需要根据系统表来更新缓存,
即数据库中的数据发生了改变, 此时更新本次添加的缓存
对上面的代码添加方法
public static void SetWithSql(string key, object data, string connStr, string sql, CacheEntryRemovedCallback callback)
{
if (data == null)
return;
Cache.Add(new CacheItem(key, data), SqlChangePolicy(connStr, sql, callback));
}
private static CacheItemPolicy SqlChangePolicy(string connStr,string sql, CacheEntryRemovedCallback callback)
{
SqlDependency.Start(connStr);
using (SqlConnection conn = new SqlConnection(connStr))
{
using (SqlCommand command = new SqlCommand(sql, conn))
{
command.Notification = null;
conn.Open();
SqlDependency dependency = new SqlDependency(command);
dependency.AddCommandDependency(command);
SqlChangeMonitor monitor = new SqlChangeMonitor(dependency);
CacheItemPolicy policy = new CacheItemPolicy();
policy.ChangeMonitors.Add(monitor);
command.ExecuteScalar();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(60*24);
policy.RemovedCallback = callback;
return policy;
}
}
}
添加cache项的时候, 传入SqlConnection和相应的sql, 目的是当sql对应的查询结果发生变化的时候, 清除此项缓存
注意是清除, 可以看到改方法有一个CacheEntryRemovedCallback参数,当此项被清除后会调用该callback方法
如果想"更新", 现在看到这个callback方法应该知道怎么做了
看着微软的帮助一步一步做下来简单, 但出了一个问题,就是刚Add进去, 马上CacheEntryRemovedCallback方法就被调用了, 数据改变了? 确认一下没有,
继续研究帮助,
看一下SqlChangeMonitor的构造函数, 参数是SqlDependency
SqlDependency是System.Data.SqlClient 命名空间中的,
微软这样说:SqlDependency 对象都表示应用程序和 SQL Server 实例之间的查询通知依赖项。 应用程序可以创建 SqlDependency 对象并进行注册以接收通知通过 OnChangeEventHandler 事件处理程序。
原来此对象是数据库中做监视和通知用的, 被"征用"过来的.
这就好办了, 根据帮助文档, 发现这个sql的要求真不是一般的严格
现在说一下这个"sql", 这个sql首先要求是一个select语句,然后:
多吧, 还有个问题,就是要启用数据库的BROKER
ALTER DATABASE database_name SET TRUSTWORTHY ON WITH ROLLBACK IMMEDIATE ALTER DATABASE database_name SET ENABLE_BROKER WITH ROLLBACK IMMEDIATE ALTER AUTHORIZATION ON DATABASE::database_name TO sa