详解C#中普通缓存的使用

 更新时间:2021年05月06日 08:26:02   作者:陈大宝  
缓存的概念及优缺点在这里就不多做介绍,当然缓存包含多种有普通缓存、客户端缓存、DNS缓存、反向代理缓存以及分布式缓存等等。今天主要聊一聊C#通过编码来实现普通的缓存、话不多说直接上代码。

一、首先,新建控制台程序(.NET Core)、以下为项目结构

  1. CacheHelper缓存帮助类
  2. DemoTest 为测试有无缓存的Demo代码
  3. Program 你们懂得 就不多说了

二、编写缓存类

public class CacheHelper
    {
        //缓存容器 
        private static Dictionary<string, object> CacheDictionary = new Dictionary<string, object>();
        /// <summary>
        /// 添加缓存
        /// </summary>
        public static void Add(string key, object value)
        {
            CacheDictionary.Add(key, value);
        }

        /// <summary>
        /// 获取缓存
        /// </summary>
        public static T Get <T>(string key)
        {
            return (T)CacheDictionary[key];
        }


        /// <summary>
        /// 缓存获取方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">缓存字典容器对应key</param>
        /// <param name="func">委托方法 传入操作对象</param>
        /// <returns></returns>
        public static T GetCache<T>(string key, Func<T> func)
        {
            T t = default(T);
            if (CacheHelper.Exsits(key))
            {
                //缓存存在,直接获取原数据
                t = CacheHelper.Get<T>(key);
            }
            else
            {
                //缓存不存在,去生成缓存,并加入容器
                t = func.Invoke();
                CacheHelper.Add(key, t);
            }
            return t;
        }

        /// <summary>
        /// 判断缓存是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool Exsits(string key)
        {
            return CacheDictionary.ContainsKey(key);
        }

public static T GetCache<T>(string key, Func<T> func)我这里直接使用泛型委托封装了缓存的方法了。当然你也可以不封装直接使用if else 判断

if (CacheHelper.Exsits(key)){} else{}

但是实际开发使用缓存应该不是一个地方使用缓存、频繁的使用if else 判断代码有点冗余、所有我就使用采用泛型委托方式封装方法 这个大家可以自行选择
  以上一般采用静态字典添加缓存数据、为了有更好的兼容性我这里直接采用泛型(泛型的好处这里就不多说了、总之性能相对更好、能够提高代码的重用性)

三、编写有缓存和没有缓存方法

public class DemoTest
    {
        /// <summary>
        /// 使用缓存测试
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public static List<People> CacheTest(int count)
        {
            People people = new People();


            List<People> ListPeople = new List<People>();
            for (int i = count; i < 100000; i++)
            {
                Console.WriteLine($"------第{i}次请求------");
                //int result = DataSource.GetDataByDB(666);

                //key的名字一定要确保请求的准确性 DataSource GetDataByDB 666缺一不可
                string key = "DataSource_GetDataByDB_666";
                ListPeople = CacheHelper.GetCache(key, () => DemoTest.GetListData());
                Console.WriteLine($"第{i}次请求获得的数据为:{people}");
           
            }
            return ListPeople;
        }

        /// <summary>
        /// 没有使用缓存
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public static List<People> NoCacheTest(int count)
        {
            People people = new People();


            List<People> ListPeople = new List<People>();
            for (int i = count; i < 100000; i++)
            {
                Console.WriteLine($"------第{i}次请求------");
                //int result = DataSource.GetDataByDB(666);

                //key的名字一定要确保请求的准确性 DataSource GetDataByDB 666缺一不可
                string key = "DataSource_GetDataByDB_666";

                //if (CacheHelper.Exsits(key))
                //{
                //    //缓存存在,直接获取原数据
                //    result = CacheHelper.Get<int>(key);
                //}
                //else
                //{
                //    //缓存不存在,去生成缓存,并加入容器
                //    result = 78;
                //    CacheHelper.Add(key, result);
                //}
                ListPeople = GetListData();
                Console.WriteLine($"第{i}次请求获得的数据为:{people}");
            }
            return ListPeople;

        }

        /// <summary>
        /// 读取数据源 这里模拟数据源读取 循环3000
        /// </summary>
        /// <returns></returns>
        public static List<People> GetListData()
        {
            List<People> peoplesList = new List<People>();


            for (int i = 0; i < 3000; i++)
            {
                People people = new People()
                {
                    Age = i,
                    Name = "陈大宝" + i.ToString()
                };

                peoplesList.Add(people);
            }return peoplesList;
        }
    }

四、控制台上端调用

class Program
    {
        static void Main(string[] args)
        {

            {
                Console.WriteLine("******************缓存测试****************");
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                var iResulr = DemoTest.CacheTest(0);

                stopwatch.Stop();

                Console.WriteLine("有缓存消耗时间为" + stopwatch.ElapsedMilliseconds);
            }
            {
                Console.WriteLine("*****************没有缓存测试****************");
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                var iResulr = DemoTest.NoCacheTest(0);

                stopwatch.Stop();

                Console.WriteLine("没有缓存消耗时间为" + stopwatch.ElapsedMilliseconds);
            }
        }
    }

循环10万次有缓存消耗时间

循环10万次没有有缓存消耗时间

以上为循环10万次验证后分析:以上消耗时间为毫秒、有缓存 22282毫秒大致为0.37分钟左右。没有缓存 82417毫秒大致为1.37分钟左右、两者相差1分钟左右、那么有朋友可能会发现你这也没快多少啊、但是兄弟们实际我们在访问时一分钟已经是相当久了、你能想象调用一次接口访问时间如果超过一分钟是什么感觉?那毫无疑问肯定得炸毛、而且我们访问数据实际第一次肯定是要到关系型数据中获取数据的、如果使用缓存直接第二次直接取内存缓存(不用去再去操作数据库IO了)、但是不使用缓存每次去操作数据库、当用户量稍微多一点数据库它是有性能开销越来越大、所以缓存是非常有效的、也是我们最能直观立竿见影的效果。

总结一下哈:

到这里,缓存的使用基本结束了。最好值得一提的是,缓存尽量在数据量小、重复查询量大的情况下使用。因为缓存也是要耗内存的,毕竟我们服务器内存是有限的!、当然了会有小伙伴会说我们都已经用Redis等等、确实现在缓存当然用的比较多是Redis了、Redis好处这里就不先谈了、总之本次文章是让没有了解普通缓存是如何使用得的小伙伴熟悉并了解、其实在这种方式在有些场景也是有它的好处的。

以上就是详解C#中普通缓存的使用的详细内容,更多关于c# 普通缓存的使用的资料请关注脚本之家其它相关文章!

相关文章

  • C#实现简易计算器功能(1)(窗体应用)

    C#实现简易计算器功能(1)(窗体应用)

    这篇文章主要为大家详细介绍了C#实现简易计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • VS中模仿WPF模板创建最简单的WPF程序

    VS中模仿WPF模板创建最简单的WPF程序

    这篇文章主要为大家详细介绍了VS中模仿WPF模板创建最简单的WPF程序的相关资料,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • C#中判断本地系统的网络连接状态的方法

    C#中判断本地系统的网络连接状态的方法

    C#中一般通过InternetGetConnectedState函数返回本地系统的网络连接状态,下面简单介绍下,需要的朋友可以参考下
    2013-10-10
  • c#事件使用示例详解

    c#事件使用示例详解

    这篇文章主要介绍了c#事件使用方法,下面我们利用一个例子来加深我们对事件的理解,需要的朋友可以参考下
    2014-04-04
  • 自动输出类的字段值实用代码分享

    自动输出类的字段值实用代码分享

    有点时候在测试的时候希望打印输出返回对象的各字段的值,采用下面的代码可以很方便的列出对象的各字段值
    2013-12-12
  • C#中常用的运算符总结

    C#中常用的运算符总结

    在本篇文章里小编给大家分享了关于C#中常用的运算符的知识点总结,需要的朋友们跟着学习下。
    2019-03-03
  • C#身份证号码验证是否正确

    C#身份证号码验证是否正确

    这一篇关于C#语言验证18位身份证号码的验证方法和实例代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2015-09-09
  • 详解C#应用程序如何实现多屏显示

    详解C#应用程序如何实现多屏显示

    这篇文章主要为大家详细介绍了C#如何实现把主屏运行程序中多个窗体移动到各个扩展屏幕位置显示,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-05-05
  • c# 实现子窗口关闭父窗口也关闭的简单实例

    c# 实现子窗口关闭父窗口也关闭的简单实例

    下面小编就为大家带来一篇c# 实现子窗口关闭父窗口也关闭的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • C#使用正则表达式实现汉字转拼音

    C#使用正则表达式实现汉字转拼音

    这篇文章主要为大家详细介绍了C#如何使用正则表达式实现汉字转拼音的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01

最新评论