NET下三种缓存机制(Winform里面的缓存使用 )

原文(http://www.cnblogs.com/wuhuacong/p/3526335.html)非常感谢伍华聪作者的分享!

缓存在很多情况下需要用到,合理利用缓存可以一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力。本文主要针对自己在Winform方面的缓存使用做一个引导性的介绍,希望大家能够从中了解一些缓存的使用场景和使用方法。缓存是一个中大型系统所必须考虑的问题。为了避免每次请求都去访问后台的资源(例如数据库),我们一般会考虑将一些更新不是很频繁的,可以重用的数据,通过一定的方式临时地保存起来,后续的请求根据情况可以直接访问这些保存起来的数据。这种机制就是所谓的缓存机制。

.NET 4.0的缓存功能主要由三部分组成:System.Runtime.Caching,System.Web.Caching.Cache和Output Cache。

System.Runtime.Caching这是在.NET 4.0中新增的缓存框架,主要是使用MemoryCache对象,该对象存在于程序集System.Runtime.Caching.dll。

System.Web.Caching.Cache这个则是在.NET2.0开始就一直存在的缓存对象,一般主要用在Web中,当然也可以用于Winform里面,不过要引用System.Web.dll。

Output Cache则是Asp.NET里面使用的,在ASP.NET 4.0之前的版本都是直接使用System.Web.Caching.Cache来缓存HTML片段。在ASP.NET 4.0中对它进行了重新设计,提供了一个OutputCacheProvider供开发人员进行扩展,但是它默认情况下,仍然使用System.Web.Caching.Cache来做做缓存。

1、自定义Hastable的缓存处理。

除了上面三种的缓存机制,一般我们还可以在静态对象里面通过HashTable或者Dictionary的方式进行自定义的缓存存储和使用。

例如我在我自己所开发的程序里面,都使用了工厂类来创建业务对象,由于创建业务对象以及数据访问层对象,是一个在界面或者中间层反复调用的操作,因此需要把经常调用的对象把它存储起来,下载调用的时候,直接从内存中取出来即可。如下面的BLLFactory类,就是一个基于泛型对象的业务类的创建操作,使用了基于Hashtable的静态对象进行缓存处理。

 1 /// <summary>
 2 /// 对业务类进行构造的工厂类
 3 /// </summary>
 4 /// <typeparam name="T">业务对象类型</typeparam>
 5 public class BLLFactory<T> where T : class
 6 {
 7 private static Hashtable objCache = new Hashtable();
 8 private static object syncRoot = new Object();
 9
10 /// <summary>
11 /// 创建或者从缓存中获取对应业务类的实例
12 /// </summary>
13 public static T Instance
14 {
15 get
16 {
17 string CacheKey = typeof(T).FullName;
18 T bll = (T)objCache[CacheKey];  //从缓存读取
19 if (bll == null)
20 {
21 lock (syncRoot)
22 {
23 if (bll == null)
24 {
25 bll = Reflect<T>.Create(typeof(T).FullName, typeof(T).Assembly.GetName().Name); //反射创建,并缓存
26 objCache.Add(typeof(T).FullName, bll);
27 }
28 }
29 }
30 return bll;
31 }
32 }
33 }

2、使用.NET4.0的MemoryCache对象实现缓存

MemoryCache的使用网上介绍的不多,不过这个是.NET4.0新引入的缓存对象,估计主要是替换原来企业库的缓存模块,使得.NET的缓存可以无处不在,而不用基于特定的Windows版本上使用。

首先我们使用来创建一个基于MemoryCache的辅助类MemoryCacheHelper,方便调用进行缓存处理。

 1 /// <summary>
 2     /// 基于MemoryCache的缓存辅助类
 3     /// </summary>
 4     public static class MemoryCacheHelper
 5     {
 6         private static readonly Object _locker = new object();
 7
 8         public static T GetCacheItem<T>(String key, Func<T> cachePopulate, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
 9         {
10             if(String.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
11             if(cachePopulate == null) throw new ArgumentNullException("cachePopulate");
12             if(slidingExpiration == null && absoluteExpiration == null) throw new ArgumentException("Either a sliding expiration or absolute must be provided");
13
14             if(MemoryCache.Default[key] == null)
15             {
16                 lock(_locker)
17                 {
18                     if(MemoryCache.Default[key] == null)
19                     {
20                         var item = new CacheItem(key, cachePopulate());
21                         var policy = CreatePolicy(slidingExpiration, absoluteExpiration);
22
23                         MemoryCache.Default.Add(item, policy);
24                     }
25                 }
26             }
27
28             return (T)MemoryCache.Default[key];
29         }
30
31         private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration)
32         {
33             var policy = new CacheItemPolicy();
34
35             if(absoluteExpiration.HasValue)
36             {
37                 policy.AbsoluteExpiration = absoluteExpiration.Value;
38             }
39             else if(slidingExpiration.HasValue)
40             {
41                 policy.SlidingExpiration = slidingExpiration.Value;
42             }
43
44             policy.Priority = CacheItemPriority.Default;
45
46             return policy;
47         }
48     }

这个辅助类只有一个public方法,就是GetCacheItem,使用的时候,需要指定key和获取数据的处理代理,还有缓存的过期时间,是基于TimeSpan的还是基于绝对时间的,选择其一。

上面的辅助类,我们在什么情况下会使用到呢?

假如在一个工作流模块中用到了人员ID,而人员ID需要进行人员名称的转义,人员信息我们一般知道放在权限系统模块里面,那么如果在工作流里面需要频繁对人员ID进行转义,那么就需要方法调用权限系统的接口模块,这样处理就可以使用缓存模块进行优化处理的了。

 1 void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
 2         {
 3             if (e.Column.FieldName.Equals("ProcUser") || e.Column.FieldName.Equals("ProcUid") || e.Column.FieldName.Equals("UserId"))
 4             {
 5                 if (e.Value != null)
 6                 {
 7                     e.DisplayText = SecurityHelper.GetUserFullName(e.Value.ToString());
 8                 }
 9             }
10         }

其中的SecurityHelper.GetUserFullName是我对调用进行基于缓存的二次封装,具体逻辑如下所示。

 1 /// <summary>
 2         /// 根据用户的ID,获取用户的全名,并放到缓存里面
 3         /// </summary>
 4         /// <param name="userId">用户的ID</param>
 5         /// <returns></returns>
 6         public static string GetUserFullName(string userId)
 7         {
 8             string key = "Security_UserFullName" + userId;
 9             string fullName = MemoryCacheHelper.GetCacheItem<string>(key,
10                 delegate() { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); },
11                 new TimeSpan(0, 30, 0));//30分钟过期
12             return fullName;
13         }

MemoryCacheHelper的方法GetCacheItem里面的Func<T>我使用了一个匿名函数用来获取缓存的值。

1 delegate() { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); }

而调用BLLFactory<User>.Instance.GetFullNameByID则是从数据库里面获取对应的数据了。

这样在第一次或者缓存过期的时候,自动调用业务对象类的方法来获取数据了。

最后,在界面上调用GetUserFullName的方法即可实现基于缓存方式的调用,程序第一次使用的,碰到指定的键没有数据,就去数据库里面获取,以后碰到该键,则直接获取缓存的数据了。

下面图形是程序具体的实现效果。

当然,以上两种方式都还可以通过AOP的注入方式实现代码的简化操作,不过由于对AOP的引入,会涉及到更多的知识点,而且熟悉程序还不够,所以依然采用较为常用的方式来处理缓存的数据。

时间: 2024-12-19 14:26:04

NET下三种缓存机制(Winform里面的缓存使用 )的相关文章

Oracle基础学习2--Oracle登录与三种验证机制

首先,Oracle安装完毕有三个默认用户 ?  Sys:数据库对象的拥有者.权限最高.password在安装的时候(口令管理)能够改变 ?  System:数据库管理员,password为manager ?  Scott:一个普通用户,password为tiger 再看连接Oracle的三种验证机制 ?  操作系统验证(具体解释见以下) ?  password文件验证 ?  数据库验证 注:前两者适用于系统用户,比方:Sys.System等:最后一个适用于普通用户.比方:Scott. 再看Ora

Oracle数据库的三种验证机制

关于超级管理员登陆不需要密码因为: 数据库的三种验证机制: 操作系统验证(具有sysdba和sysopera的用户) 密码文件验证(具有sysdba和sysopera的用户) 数据库验证(普通用户) 因为不需要密码是不安全的,所以一般在计算机管理中的用户组ora_dba把Administrator删除,删除之后就要输入密码了. 启动监听:lsnrctl start 查看监听:lsnrctl status 停止监听:lsnrctl stop 1.oracle 数据服务器包括:实例进程和数据库:  

【css笔记】css中的盒模型和三种定位机制(固定定位,绝对定位,浮动)

html页面上的元素都可以看成是框组成的,框通过三种定位机制排列在一起就过程了我们看到的页面.而框就是盒模型. 盒模型 1.页面上的每个元素可以看成一个矩形框,每个框由元素的内容,内边距,边框和外边距组成. 2.如果在元素上添加背景,则背景是边框, 内边距和内容组成的区域. 3.在css中width和height指的是内容区域的宽度和高度.增加内边距,边框和外边距不会影响内容区域的尺寸,但会增加元素框的总尺寸.即width=element 注意:ie的盒模型中,width指的是内容,内边距,和边

gtest 三种事件机制

前言: 1.首先说明gtest中事件的结构层次: 测试程序:一个测试程序只有一个main函数,也可以说是一个可执行程序是一个测试程序.该级别的事件机制会在程序的开始和结束执行. 测试套件:代表一个测试用例的集合体,该级别的事件机制会在整体的测试案例开始可结束执行. 测试用例:该级别的事件机制会在每个测试用例开始和结束都执行. gtest中的事件机制是指在测试前和测试后提供给用户自行添加操作的机制,而且次机制也可用让同一测试套件下的测试用例共享数据. 一.全局的事件机制(针对整个测试程序) 实现全

earlysuspend、autosleep以及wakeup_count三种休眠机制的分析和比较

一.Opportunistic sleep引言 1. 背景 (1) android 面临的问题 Opportunistic sleep: 当没有任务时,需要寻找时机,进入suspended (2) 3类同步问题 a. 内核:driver处理event的过程中,系统不能suspend b. 用户:用户进程处理的过程中系统不能suspend c. 内核与用户交互: 休眠过程中,触发event, 需abort suspend流程; event 事件需用户态处理完毕后,才能suspend; 2. ear

VMware下三种网卡(仅主机,桥接,NAT)模式

VMware下三种网卡(仅主机,桥接,NAT)模式 前言: 最近在学习利用Wireshark抓包时,朋友遇到了一个棘手的问题:在虚拟机上的两个操作系统之间不能互相通信,无法抓取到两者访问http的包百思不得其解,纠结了好久之后,明白了是两者系统的网卡模式不一样不能通信的缘故.这才发现自己对这三种模式没有清晰的认识,赶紧来学习下. 一.桥接模式: 示意图: 物理机上有一个自身的网卡,虚拟机虚拟一个虚拟网卡,两者可以通过虚拟出的交换机连接到外网. 二.NAT模式: 示意图: 物理机上有一个自身的网卡

VMware下三种网络连接模式

目录 VMware下三种网络连接模式 VMware下三种网络连接模式 Bridged(桥接模式) 在桥接模式下,VMware虚拟出来的操作系统就像是局域网中的一独立的主机,它可以访问该类网段内任何一台机器. 桥接网络环境下需要做到: 手动为虚拟机系统配置IP地址.子网掩码 在桥接模式下,虚拟机与物理机处于同一个网段,(举个例子,物理机IP:192.168.1.2,虚拟机IP:192.168.1.3)这样虚拟系统才能和真实主机进行通信. 关于桥接网络的使用说明: 当你想利用VMware在局域网内新

Linux 下三种方式设置环境变量

1.在Windows 系统下,很多软件安装都需要配置环境变量,比如 安装 jdk ,如果不配置环境变量,在非软件安装的目录下运行javac 命令,将会报告找不到文件,类似的错误. 2.那么什么是环境变量?简单说,就是指定一个目录,运行软件的时候,相关的程序将会按照该目录寻找相关文件. 设置变量对于一般人最实用的功能就是: 不用拷贝某些dll文件到系统目录中了,而path 这一系统变量就是系统搜索dll文件的一系列路径 在Linux系统下,如果你下载并安装应用程序,很有可能在键入它的名称的时候出现

Apache下三种MPM模式:prefork,worker和event

MPM(Multi-Processing Module,多进程处理模块):prefork,worker和event 查看Apache的模式,可以使用httpd -V命令来查看:  /usr/local/apache2/bin/httpd  -V Server version: Apache/2.2.29 (Unix) Server built:   Aug 20 2015 20:11:21 Server's Module Magic Number: 20051115:36 Server load