一、在添加一个缓存项时,允许指定一个过期策略,这个过期策略对象要实现ICacheItemExpiration接口,常见的过期策略有:
绝对过期时间 : AbsoluteTime
表达式表示的时间过期策略:ExtendedFormatTime
程序运行中一直不会过期NeverExpired:
每次读取之后,再延长指定的时间后才会过期:SlidingTime。
文件依赖:FileDependency
二、自己实现一个,缓存项依赖:CacheItemDependency
参考FileDependency的实现,缓存项的过期与否取决于文件是否发生了变化,我们自己实现一个过期策略,就是缓存项的过期与否取决于另一个NeverExpired的缓存项是否发生了变化。
代码如下:

Code
[Serializable]
[ComVisible(false)]
public class CacheItemDependency : ICacheItemExpiration

{
private readonly string dependencyCacheKey;

private System.Int32 lastCount;


Constructor#region Constructor

/**//// <summary>
/// Constructor with one argument.
/// </summary>
/// <param name="cacheKey">Indicates the key of the cache item</param>
public CacheItemDependency(string cacheKey)

{
dependencyCacheKey = cacheKey;
ICacheManager cacheManager = CacheFactory.GetCacheManager();
lastCount = Int32.MinValue;
if (cacheManager != null)

{
if (cacheManager.Contains(cacheKey))

{
object o = cacheManager.GetData(cacheKey);
if (o != null)

{
this.lastCount = (int)o;
}

lastCount = (int)cacheManager.GetData(cacheKey);
}
else

{
cacheManager.Add(cacheKey, lastCount);
}
}
}
#endregion


Properties#region Properties

/**//// <summary>
/// Gets the key of the dependent Cache Item.
/// </summary>
/// <value>
/// The key of the dependent Cache Item.
/// </value>
public string DependencyCacheKey

{

get
{ return dependencyCacheKey; }
}

/**//// <summary>
/// Gets the Last Count.
/// </summary>
/// <value>
/// The Count of the last setup.
/// </value>
public System.Int32 LastCount

{

get
{ return lastCount; }
}
#endregion


ICacheItemExpiration Members#region ICacheItemExpiration Members

/**//// <summary>
/// Specifies if the item has expired or not.
/// </summary>
/// <returns>Returns true if the item has expired, otherwise false.</returns>
public bool HasExpired()

{
ICacheManager cacheManager = CacheFactory.GetCacheManager();
//throw new Exception("The method or operation is not implemented.");
if (cacheManager == null)

{
return true;
}

System.Int32 currentCount = (int)cacheManager.GetData(dependencyCacheKey);
if (currentCount != lastCount)

{
return true;
}
else

{
return false;
}
}


/**//// <summary>
/// Notifies that the item was recently used.
/// </summary>
public void Notify()

{
}


/**//// <summary>
/// Not used
/// </summary>
/// <param name="owningCacheItem">Not used</param>
public void Initialize(CacheItem owningCacheItem)

{
}
#endregion
}
三、使用方法
1、更新缓存所依赖的缓存项。代码如下:

Code

/**//// <summary>
/// 更新所有以cacheKeys中元素为key的缓存项
/// </summary>
/// <param name="cacheKeys">缓存项的key的数组</param>
public static void UpdateCacheDependency(string[] cacheKeys)

{
ICacheManager cacheManager = CacheFactory.GetCacheManager();
foreach (string cacheKey in cacheKeys)

{
string cacheItemCache = GetCacheKey(cacheKey);
if (cacheManager != null && cacheManager.Contains(cacheItemCache))

{
int lastCount = (int)cacheManager.GetData(cacheItemCache);
if (lastCount < Int32.MaxValue)

{
lastCount++;
}
else

{
lastCount = Int32.MinValue;
}
// 这一句的作用在于更新以cacheKey为key的缓存项,从而使依赖于此缓存项的缓存项失效.
// 当以cacheKey为Key的缓存项中的数据(这里是lastCount)变化时,是的依赖于此缓存项的缓存失效
cacheManager.Add(cacheKey, lastCount);
}
}
}
2、每次更新数据库中的表时,调用UpdateCacheDependency方法。
在上述代码中cacheKey可以用数据库中标的名称。
还有一个问题就是 每次更新数据库中的表时,都要调用UpdateCacheDependency方法,是不是很烦,这也是没有办法的,必须调用,否则 依赖于 以cacheKey为Key的缓存项 的缓存项 不会失效,一般可以在数据访问的基类中将Insert\Update\Delete执行的地方调用这个方法即可。
如果用DataSet,代码类似这样:

Code
public int Update(DataSet dataSet, bool isStoredProc, bool removeCache, string[] cacheItemKeys)

{
int cnt = db.UpdateDataSet(dataSet, dataSet.Tables[0].TableName,
PrepareCommand(insertCommand, InsertStoredProc, new PopulateParameters(PopulateInsertParamters), isStoredProc),
PrepareCommand(updateCommand, UpdateStoredProc, new PopulateParameters(PopulateUpdateParamters), isStoredProc),
PrepareCommand(deleteCommand, DeleteStoredProc, new PopulateParameters(PopulateDeleteParamters), isStoredProc),
UpdateBehavior.Standard);

if (removeCache && cacheItemKeys != null)

{
DataAccessUtil.UpdateCacheDependency(cacheItemKeys);
}
return cnt;
}
如果用实体类,代码类似这样:

Code
protected bool ExecuteNonQuery(TEntity entity, string spName, PopulateParamters<TEntity> populateParamters, HandleReturnValue handleReturnValue, bool removeCache, string[] cacheKeys)
{
int returnValue = -1;
try
{
Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetStoredProcCommand(spName);
if (populateParamters != null)
{
populateParamters(entity, db, cmd);
}
if (handleReturnValue != null)
{
db.AddParameter(cmd, "ReturnValue", DbType.Int32, ParameterDirection.ReturnValue, String.Empty, DataRowVersion.Default, null);
}
db.ExecuteNonQuery(cmd);
returnValue = 0;
if (handleReturnValue != null)
{
returnValue = DataAccessHelper.GetReturnValue(db, cmd);
handleReturnValue(returnValue, "");
}
}
catch
{
throw;
}
if (removeCache && cacheKeys != null && cacheKeys.Length > 0)
{
UpdateCacheDependency(cacheKeys);
}
return (returnValue == 0);
}