在应用程序中有许多向资料库读取资料的动作,为了增加程序效能, 有 2 个方向可以调整。
第 1 种是直接调效 SQL 的效能,减少 SQL 的不良写法,让资料库查找资料的速度变快。
第 2 种是直接将上次查到的结果,先暂存在记忆体中,如果资料库的内容没有变动的话,直接回传刚刚已查过的资料内容,可以有效增加系统回应速度。
在 C# .Net 4.0 开始,我们可以善用 System.Runtime.Caching 的 MemoryCache 的快取机制来增加程序回应的速度。
记忆体内的存取速度远远比向资料库取资料快很多,而资料库取得的资料有时会因为网路限制而变更慢,所以在建置应用程序的时候,适时的加入记忆体快取机制在专案中可以有效增加效能。
MemoryCache 是实作记忆体内存取快取的方法。快取可以减少产生内容的工作,将已取得的资料暂存在记忆体空间,并指定暂存时间,可依时间到期而回收或是手动回收。
若应用程序重启时,原有存在快取的资料将会一并自动清除。此概念跟电脑的记忆体是相同的,存放在记忆体内的资料,当电脑重开机後也会一并自动清除。
此范例是说明读写快取的方法,而快取存活时间为 60 分钟後即立刻回收
ObjectCache Cache = MemoryCache.Default;
string CacheName = "Cache1";
// 检查快取是否存在
bool isSet = Cache[CacheName] != null;
// 取得资料库取得物件(省略动作)
DataTable dt = new DataTable();
// 写入快取 (指定时间後回收快取)
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(60); // 60 分钟後回收
Cache.Add(new CacheItem(CacheName, dt), policy);
// 读取快取
dt = (DataTable)Cache[CacheName];
// 移除快取
Cache.Remove(CacheName);
此范例讲解了存取 4 个主要动作,
1: 是否存在
2: 写入
3: 读取
4: 移除。
向记忆体存取需指定一个名称,Ex: Cache1,存取都需要用相同的名称。
范例中的 60 分钟是可以改变单位的,换成秒也是可以。
若要换成 60 秒的话,写法改成
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromSeconds (60); // 60 秒後回收
此范例是讲解资料写入快取後,如果在 60 分钟内没有被读取时则会回收,若有被读取时,则会再延长 60 分钟
ObjectCache Cache = MemoryCache.Default;
string CacheName = "Cache2";
// 检查快取是否存在
bool isSet = Cache[CacheName] != null;
// 取得资料库取得物件(省略动作)
DataTable dt = new DataTable();
// 写入快取 (指定时间未使用时回收快取)
CacheItemPolicy policy = new CacheItemPolicy();
policy.SlidingExpiration = TimeSpan.FromMinutes(60); // 若 60 分钟内未呼叫此快取就会回收,若有呼叫则会再延长 60 分钟
Cache.Add(new CacheItem(CacheName, dt), policy);
// 读取快取
dt = (DataTable)Cache[CacheName];
// 移除快取
Cache.Remove(CacheName);
此范例跟第 1 个差异就是存活时间,如果这个快取有被使用则自动延长存活时间。
此两种范例都可以依实务上的需求而选择使用。
范例中的 60 分钟若要换成 60 秒的话,写法改成
policy.SlidingExpiration = TimeSpan. FromSeconds(60); // 60秒
以上介绍了 2 种读写快取的方法,而快取还有另一种存活时间控制是 ChangeMonitors ,当有资料异动时就回收快取,但我没有实际上的应用,就没有实作范例了。
接下来我会展示我将快取常用的方法建立在 Class ,提供 4 个主要方法[ IsSet, Set, Get, Remove] 呼叫
public class AppCache
{
#region 属性
private ObjectCache Cache
{
get
{
return MemoryCache.Default;
}
}
// 因为与其他应用程序共用此记忆体快取,所以建议增加此应用程序的前置名称
private string IdNameStart = "MyProjectName_";
#endregion
#region 建构子
public AppCache()
{
}
#endregion
#region 方法
/// <summary>
/// 取得快取
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public object Get(string key)
{
return Cache[IdNameStart + key];
}
/// <summary>
/// 移除快取
/// </summary>
/// <param name="key"></param>
public void Remove(string key)
{
Cache.Remove(IdNameStart + key);
}
/// <summary>
/// 是否存在快取
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool IsSet(string key)
{
return (Cache[IdNameStart + key] != null);
}
/// <summary>
/// 设定快取
/// </summary>
/// <param name="key">KEY</param>
/// <param name="data">资料</param>
public void Set(string key, object data)
{
this.Set(key, data, "Sliding", 60);
}
/// <summary>
/// 设定快取
/// </summary>
/// <param name="key">KEY</param>
/// <param name="data">资料</param>
/// <param name="Expiration">保留别</param>
/// <param name="cacheTime">保存时间(分钟)</param>
public void Set(string key, object data, string Expiration, int cacheTime)
{
CacheItemPolicy policy = new CacheItemPolicy();
if (Expiration == "Absolute")
{
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
}
else if (Expiration == "Sliding")
{
policy.SlidingExpiration = TimeSpan.FromMinutes(cacheTime);
}
Cache.Add(new CacheItem(IdNameStart + key, data), policy);
}
#endregion
}
写好此类别,就可以方便使用。
使用的范例可以参考这个
AppCache cache = new AppCache();
// 检查Cache 是否存在
DataTable dt = null;
if (cache.IsSet("Cache1") == false)
{
// 取得资料库取得物件(省略动作)
dt = new DataTable();
// 设定新 Cache , 60 分钟後就回收快取
cache.Set("Cache1", dt, "Absolute", 60);
}
else
{
// 取得 Cache
dt = (DataTable)cache.Get("Cache1");
}
// 移除 Cache
cache.Remove("Cache1");
将常用的方法写入类别里,方便在应用程序中使用。
[C#]QR Code 网址产生与解析 (附范例)
[C#] Base32 编码/解码方法 不分大小写的编码方式
这边改成只要在聊天室输入关键字就会传出LINE emoji讯息 前面处理LINE emoji讯息的函...
开始之前先送上菜鸡的code 这是我第一次实作RWD的网页,又因为最近同步在看Bootstrap。 ...
今日时间主要给学员与组员讨论专题,另外助教也分享参赛及制作专题的心得。 ...
హలో,我是Charlie! 在Day12当中,我们完成了商品详情显示的API,而今天我们将完成後端...
上一篇介绍了Palindromes,上一题讲解了如何辨别是不是镜像字或是回文字的题目,只要先辨别出镜...