1 写在前面

此文主要参考了园子里以下两篇文章:

黄聪,Microsoft Enterprise Library 5.0 系列(一) : Caching Application Block (初级)

顾磊,[EntLib]微软企业库5.0 学习之路——第四步、使用缓存提高网站的性能(EntLib Caching)

2 前面两篇博文写的很好,很全面,为何还需要本文?

大家可以点进去看下前面的文章,黄聪写的是企业库Cache的基本用法,顾磊的文章比较深入,而且自定义了CacheHelper类,实用性更强,我也抄袭了这个类(^_^ )。

我写此文的目的主要是记录下如果在项目中引入操作Cache、缓存哪些内容及最后的单元测试等~

主要是在缓存哪些数据的问题上,可能和顾磊的文章有些不同。

3 项目中引入Cache

首先从微软网站下载并安装Enterprise Library 5.0, 我这里Cache主要用在DataAccess这个项目中,是一个类库项目,所以Config的东西先不用配置,直接添加Microsoft.Practices.EnterpriseLibrary.Caching.dll的引用,

然后添加CacheHelper类,代码:

View Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Practices.EnterpriseLibrary.Caching;
using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

using System.Reflection;

namespace DataAccess
{
    public static class CacheHelper
    {
        private static ICacheManager cache = CacheFactory.GetCacheManager();

/// <summary>
        /// Add Cache
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="isRefresh">if true, should reload data every 5 mins; default value = false</param>
        public static void Add(string key, object value, bool isRefresh)
        {
            if (isRefresh)
                cache.Add(key, value, CacheItemPriority.Normal, new ATSCacheItemRefreshAction(), new AbsoluteTime(TimeSpan.FromMinutes(5)));
            else
                cache.Add(key, value);
        }
        // Summary:
        //     Adds new CacheItem to cache. If another item already exists with the same
        //     key, that item is removed before the new item is added. If any failure occurs
        //     during this process, the cache will not contain the item being added. Items
        //     added with this method will be not expire, and will have a Normal Microsoft.Practices.EnterpriseLibrary.Caching.CacheItemPriority
        //     priority.
        //
        // Parameters:
        //   key:
        //     Identifier for this CacheItem
        //
        //   value:
        //     Value to be stored in cache. May be null.
        //
        // Exceptions:
        //   System.ArgumentNullException:
        //     Provided key is null
        //
        //   System.ArgumentException:
        //     Provided key is an empty string
        //
        // Remarks:
        //     The CacheManager can be configured to use different storage mechanisms in
        //     which to store the CacheItems.  Each of these storage mechanisms can throw
        //     exceptions particular to their own implementations.
        public static void Add(string key, object value)
        {
            Add(key, value, false);
        }

public static object Get(string key)
        {
            return cache.GetData(key);
        }

public static void Remove(string key)
        {
            cache.Remove(key);
        }
    }

[Serializable]
    public class ATSCacheItemRefreshAction : ICacheItemRefreshAction
    {

#region ICacheItemRefreshAction Members

public void Refresh(string removedKey, object expiredValue, CacheItemRemovedReason removalReason)
        {
            //when expired, reload it.
            if (removalReason == CacheItemRemovedReason.Expired)
            {
                ICacheManager c = CacheFactory.GetCacheManager();
                c.Add(removedKey, expiredValue);
            }
        }

#endregion
    }

4 缓存数据

在顾磊的文章中,他主要缓存一些Class,如ClassInfoService、StudentService等,代码如下:

View Code

/// <summary>
        /// 通用对象反射(包含缓存)
        /// </summary>
        /// <param name="className">要反射的类名</param>
        /// <returns></returns>
        public static T CreateObject(string className)
        {
            var typeName = assemblyString + "." + className;
            //判断对象是否被缓存,如果已经缓存则直接从缓存中读取,反之则直接反射并缓存
            var obj = (T)CacheHelper.GetCache(typeName);
            if (obj == null)
            {
                obj = (T)Assembly.Load(assemblyString).CreateInstance(typeName, true);
                CacheHelper.Add(typeName, obj, true);
            }
            return obj;
        }
public static IStudentService CreateStudent()
        {
            string typeName = assemblyString + ".StudentService";
            if (CacheHelper.GetCache(typeName) != null)
            {
                return (IStudentService)CacheHelper.GetCache(typeName);
            }
            else
            {
                IStudentService service = (IStudentService)Assembly.Load(assemblyString).CreateInstance(typeName, true);
                CacheHelper.Add(typeName, service, true);
                return service;
            }

而像StudentService这种Class,如果New StudentService()这样一个实例的话,所占的CPU和内存都是很小的,我觉得更有必要的是缓存数据,从数据库中查询回来的数据。

我们看下顾磊代码中如何操作数据的:

class StudentManage:

View Code

private static readonly IStudentService studentService = DataAccess<IStudentService>.CreateObject("StudentService");

public Student SelectById(int id)
        {
            return studentService.SelectById(id);

class StudentService:

View Code

/// <summary>
        /// 根据学生ID查询学生对象
        /// </summary>
        /// <param name="id">学生ID</param>
        /// <returns></returns>
        public Student SelectById(int id)
        {
            Student student = null;
            Database db = DBHelper.CreateDataBase();
            StringBuilder sb = new StringBuilder();
            sb.Append("select * from Student ");
            sb.Append(" where ID=@ID");
            DbCommand cmd = db.GetSqlStringCommand(sb.ToString());
            db.AddInParameter(cmd, "@ID", DbType.Int32, id);
 
            using (IDataReader reader = db.ExecuteReader(cmd))
            {
                if (reader.Read())
                {
                    student = new Student()
                    {
                        Id = reader.GetInt32(0),
                        ClassId = reader.GetInt32(1),
                        Sid = reader.GetString(2),
                        Password = reader.GetString(3),
                        Name = reader.GetString(4),
                        Sex = reader.GetInt32(5),
                        Birthday = reader.GetDateTime(6),
                        IsAdmin = reader.GetInt32(7)
                    };
                }
            }
 
            return student;

大家从上面的代码可以看出,缓存中存放了StudentService这个类,但是在SelectById(int id)这个函数中,并没有缓存任何东西,还是每次从数据库中查询数据,这样设计缓存,对程序性能的提升是十分有限的。

5 我程序中如何缓存数据

我还是用上面顾磊的代码吧,那个好理解。然后我将每次查询到的数据缓存起来,如果下次查询,先从缓存中取数据,有则自动返回数据;没有,则从数据库中查询,然后添加到缓存中,缓存有自动的数据过期机制,过期的数据会自动删除。

View Code

public Student SelectByIdWithCache(int id)
        {
            Student student = (Student)CacheHelper.GetCache(id.ToString());
            if (student == null)
            {
                student = SelectById(id);
                CacheHelper.Add(id.ToString(), student);
            }
            return student;

这里可能上面的代码不是十分恰当,但是为了让大家更清楚我的意图,及上面的代码十分简洁、易懂。

主要是我项目程序中有这样的特情况,查询参数是一个TableParameters,里面有很多字段:

View Code

public class TableParameters : IParameters<tblTable>
    {
        public Guid? tableGuid { get; set; }
        public string tableName { get; set; }
        public string tableDesc { get; set; }
        public Guid? tableTypeGuid { get; set; }
        public Guid? schemeGuid { get; set; }
        public Guid index1TypeGuid { get; set; }
        public Guid? latestTableVersionGuid { get; set; }
        public Guid? tableFormatGuid { get; set; }
        public Guid? index2TypeGuid { get; set; }

在第一次会通过一个条件,查询得到一个List,之后会直接传输一个Guid过来,而这个guid往往会包含在上面的结果中,所以第一件会将List缓存,详细代码:

View Code

public List<tblTable> GetQueryList(IParameters<tblTable> t)
        {
            TableParameters param = (TableParameters)t;

List<tblTable> query = new List<tblTable>();
            if (param.tableGuid != null)
            {
                tblTable result = (tblTable)CacheHelper.Get(GuidTable + param.tableGuid.Value.ToString());
                if (result != null)
                {                  
                    query.Add(result);
                    return query;
                }
            }

var _tableQuery = from c in db.tblTable.Expand("TableType").Expand("TableFormat").Expand("Scheme").Expand("Index1Type").Expand("Index2Type").Expand("LatestTableVersionGUID")
                                               select c;
            if (param.tableGuid != null)
            {
                _tableQuery = _tableQuery.Where(n => n.TableGUID == param.tableGuid.Value);
            }
            if (!string.IsNullOrEmpty(param.tableName))
            {
                _tableQuery = _tableQuery.Where(n => n.TableName.Contains(param.tableName));
            }
            if (param.tableTypeGuid != null)
            {
                _tableQuery = _tableQuery.Where(n => n.TableType.TableTypeGUID == param.tableTypeGuid.Value);
            }
            if (param.tableFormatGuid != null)
            {
                _tableQuery = _tableQuery.Where(n => n.TableFormat.TableFormatGUID == param.tableFormatGuid.Value);
            }
            if (param.schemeGuid != null)
                _tableQuery = _tableQuery.Where(n => n.Scheme.SchemeGUID == param.schemeGuid.Value);
            
            query = _tableQuery.ToList<tblTable>();
            foreach (var tb in query)
            {
                CacheHelper.Add(GuidTable + tb.TableGUID.ToString(), tb);
            }
            return query;

6 单元测试

这个单元测试不是测试顾磊代码的,是我项目中测试TableManager的,因为顾磊的代码更简明,所以上面我还是贴出了他的代码,至于单元测试,还是随便贴个我项目的,因为顾磊那个我没数据,没法写,呵呵~

View Code

/// <summary>
        ///A test for GetQueryList
        ///</summary>
        [TestMethod()]
        public void GetQueryListTest()
        {
           
            TableParameters t = new TableParameters();
            t.schemeGuid = new Guid("9C962C55-A598-40B8-A39B-11788161A9D8");
           
            List<tblTable> actual;
            actual = ManagerFactory.TableManager.GetQueryList(t);
            Assert.AreEqual(" Sedgwick Marsh- B & pre2000-NRA65", actual[0].TableName);
            //Assert.Inconclusive("Verify the correctness of this test method.");

7 总结

我认为缓存数据不仅仅要缓存Class类,更要缓存从数据库中查询过来的数据,这样才能最大限度的提示程序性能。

8 声明

以上纯为技术交流,对顾磊、黄聪等技术牛人十分敬佩,文中也引用了他们的文中和大量代码,再次感谢。

转载于:https://www.cnblogs.com/4kapple/archive/2011/12/31/2308619.html

如何使用缓存提高程序性能相关推荐

  1. [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(三) 利用多线程提高程序性能(下)...

    [.net 面向对象程序设计进阶] (18) 多线程(Multithreading)(二) 利用多线程提高程序性能(下) 本节导读: 上节说了线程同步中使用线程锁和线程通知的方式来处理资源共享问题,这 ...

  2. Spring MVC 异步处理请求,提高程序性能

    原文:http://blog.csdn.net/he90227/article/details/52262163 什么是异步模式 如何在Spring MVC中使用异步提高性能?一个普通 Servlet ...

  3. 利用多线程提高程序性能(for Android)

    要想搞出一个反应迅速的Android应用程序,一个很好的做法就是确保在主UI线程里执行尽量少的代码.任何有可能花费较长时间来执行的代码如果在主UI线程执行,则会让程序挂起无法响应用户的操作,所以应该放 ...

  4. 如何用AIO技术提高程序性能

    写在前面 这是一篇关于 AIO 的文章.本篇文章详细对比了几个常见的I/O模型,并且介绍了AIO相关的一些API. 我把英文原文翻译过来整理成这篇文章.目的一个是自己学习,一个是方便不习惯看英文资料的 ...

  5. .Net Core中使用ref和Spanamp;lt;Tamp;gt;提高程序性能

    一.前言 其实说到ref,很多同学对它已经有所了解,ref是C# 7.0的一个语言特性,它为开发人员提供了返回本地变量引用和值引用的机制. Span 也是建立在ref语法基础上的一个复杂的数据类型,在 ...

  6. .Net Core中使用ref和SpanT提高程序性能

    一.前言 其实说到ref,很多同学对它已经有所了解,ref是C# 7.0的一个语言特性,它为开发人员提供了返回本地变量引用和值引用的机制. Span也是建立在ref语法基础上的一个复杂的数据类型,在文 ...

  7. .NET程序性能的基本要领

    .NET 平台开发应用程序具有极高的生产力..NET 平台上强大安全的编程语言以及丰富的类库,使得开发应用变得卓有成效.但是能力越大责任越大.我们应该使用.NET框架的强大能力,但同时如果我们需要处理 ...

  8. 《深入理解计算机系统》之浅析程序性能优化

    此文已由作者余笑天授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 本文主要是基于我之前学习<深入理解计算机系统>(以下简称CSAPP)这本书第五章优化程序性能内容 ...

  9. C/C++编译器并行优化技术:并行优化针对多核处理器和多线程环境进行优化,以提高程序的并行度

    目录标题 引言 数据并行:将数据集分割成多个子集,分配给多个线程或处理器并行处理. 延迟执行与乱序执行:对指令的执行顺序进行调整,提高指令流水线的利用率和性能. 延迟执行 乱序执行 任务并行:将程序分 ...

最新文章

  1. 谈谈HTTP1.0,HTTP1.1和HTTP2.0区别
  2. org.json.JSONException: A JSONObject text must begin with #39;{#39; at character 1 of {解决方法...
  3. 从零开始编写自己的C#框架(17)——Web层后端首页
  4. 批量导出部分依赖图(PDP)
  5. VSCode搭建vue前端开发工程的配置文件-launch.json
  6. oracle psu版本确认,Oracle PSU更新
  7. 使用PMBus总线监控电源管理芯片UCD90120
  8. matlab拟合RMSE,Matlab拟合工具箱的几个误差参数说明
  9. 如何实现Solidworks批量修改工程图模板?
  10. wps指定路径不存在怎么办_WPS说目录不存在
  11. 路由器的介绍和基本原理
  12. Quorum NWR算法
  13. vmware 设置ip
  14. Day02-HTML基础
  15. 【优秀的无损音乐播放器】Audirvana for Mac 3.5.9
  16. 【板栗糖GIS】win11提示无法成功操作 因为文件包含病毒
  17. (转) CS的顶级会议和期刊
  18. oracle job
  19. win10键盘全部没反应_如何处理 win10系统惠普14q-bu101TX改win7的恢复教程 -win10使用教程...
  20. 无线传感器网络定位问题的大象群优化算法

热门文章

  1. 消息队列rabbitmq(二)windows系统erl和rabbitmq的安装
  2. TLA+ TLC模型检查器使用指南(持续更新中)
  3. 通过例子学TLA+(四)-- Send Rev Print
  4. 360浏览器兼容模式下get请求缓存解决方案
  5. 张五常的《读书方法》
  6. 性能测试中服务器关键性能指标浅析
  7. 1.心灵鸡汤-英语句子
  8. 如何把ppt文档翻译成英文?教你几种ppt翻译方法
  9. 【功能安全】【ISO26262】指南
  10. 直通车关键词 关键字 直通车排名 把握好操作直通车推广的7个技巧