• C# MemoryCache学习笔记


        很多情况下需要用到缓存,合理利用缓存一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力。为了避免每次请求都去访问后台的

    资源(例如数据库),一般会考虑将一些更新不是很频繁的、可以重用的数据,通过一定的方式临时地保存起来,后续的请求根据情况可以直接访问这

    些保存起来的数据,这种机制就是所谓的缓存机制。

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

        MemoryCache:这个是在.NET 4.0中新增的缓存框架,Namespace:System.Runtime.Caching ,Assembly:System.Runtime.Caching.dll。

        System.Web.Caching.Cache:这个是在.NET 2.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来做做缓存。

        下面演示MemoryCache的简单使用:

        1、添加一个类,命名为ConfigHelper,代码如下:

        /// <summary>
        /// 配置帮助类
        /// </summary>
        class ConfigHelper
        {
            /// <summary>
            /// 获取管理配置文件对象
            /// </summary>
            /// <param name="configPath">指定要管理的配置文件路径,如果为空或不存在,则为管理程序集默认的配置文件路径。</param>
            /// <returns></returns>
            private static Configuration GetConfiguration(string configPath = null)
            {
                if (!string.IsNullOrEmpty(configPath) && File.Exists(configPath))
                {
                    ExeConfigurationFileMap map = new ExeConfigurationFileMap
                    {
                        ExeConfigFilename = configPath
                    };
                    return ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
                }
                else
                {
                    return ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                }
            }
    
            /// <summary>
            /// 获取指定配置文件+配置名称的配置项的值
            /// </summary>
            public static string GetAppSettingValue(string key, string defaultValue = null, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                var appSetting = config.AppSettings.Settings[key];
                return appSetting.Value;
            }
    
            /// <summary>
            /// 获取所有配置值
            /// </summary>
            public static Dictionary<string, string> GetAppSettingValues(string configPath = null)
            {
                Dictionary<string, string> settingDic = new Dictionary<string, string>();
                var config = GetConfiguration(configPath);
                var settings = config.AppSettings.Settings;
                foreach (string key in settings.AllKeys)
                {
                    settingDic[key] = settings[key].ToString();
                }
                return settingDic;
            }
    
            /// <summary>
            /// 设置配置值(存在则更新,不存在则新增。)
            /// </summary>
            public static void SetAppSettingValue(string key, string value, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                var setting = config.AppSettings.Settings[key];
                if (setting == null)
                {
                    config.AppSettings.Settings.Add(key, value);
                }
                else
                {
                    setting.Value = value;
                }
    
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSettings");
            }
    
            /// <summary>
            /// 设置多个配置值(存在则更新,不存在则新增)
            /// </summary>
            public static void SetAppSettingValues(IEnumerable<KeyValuePair<string, string>> settingValues, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                foreach (var item in settingValues)
                {
                    var setting = config.AppSettings.Settings[item.Key];
                    if (setting == null)
                    {
                        config.AppSettings.Settings.Add(item.Key, item.Value);
                    }
                    else
                    {
                        setting.Value = item.Value;
                    }
                }
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSettings");
            }
    
            /// <summary>
            /// 删除配置值
            /// </summary>
            public static void RemoveAppSetting(string key, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                config.AppSettings.Settings.Remove(key);
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSettings");
            }
    
            /// <summary>
            /// 删除多个配置值
            /// </summary>
            public static void RemoveAppSettings(string configPath = null, params string[] keys)
            {
                var config = GetConfiguration(configPath);
                if (keys != null)
                {
                    foreach (string key in keys)
                    {
                        config.AppSettings.Settings.Remove(key);
                    }
                }
                else
                {
                    config.AppSettings.Settings.Clear();
                }
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("appSettings");
            }
    
            /// <summary>
            /// 获取连接字符串
            /// </summary>
            public static string GetConnectionString(string name, string defaultconnString = null, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                var connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
                if (connStringSettings == null)
                {
                    return defaultconnString;
                }
                return connStringSettings.ConnectionString;
            }
    
            /// <summary>
            /// 获取指定配置文件+连接名称的连接字符串配置项
            /// </summary>
            public static ConnectionStringSettings GetConnectionStringSetting(string name, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                var connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
                return connStringSettings;
            }
    
            /// <summary>
            /// 获取所有的连接字符串配置项
            /// </summary>
            public static Dictionary<string, ConnectionStringSettings> GetConnectionStringSettings(string configPath = null)
            {
                var config = GetConfiguration(configPath);
                var connStringSettingDic = new Dictionary<string, ConnectionStringSettings>();
                var connStringSettings = ConfigurationManager.ConnectionStrings;
                foreach (ConnectionStringSettings item in connStringSettings)
                {
                    connStringSettingDic[item.Name] = item;
                }
                return connStringSettingDic;
            }
    
            /// <summary>
            /// 设置连接字符串的值(存在则更新,不存在则新增。)
            /// </summary>
            public static void SetConnectionString(string name, string connString, string provider, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                ConnectionStringSettings connStringSettings = config.ConnectionStrings.ConnectionStrings[name];
                if (connStringSettings != null)
                {
                    connStringSettings.ConnectionString = connString;
                    connStringSettings.ProviderName = provider;
                }
                else
                {
                    connStringSettings = new ConnectionStringSettings(name, connString, provider);
                    config.ConnectionStrings.ConnectionStrings.Add(connStringSettings);
                }
    
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("connectionStrings");
            }
    
            /// <summary>
            /// 设置多个连接字符串的值(存在则更新,不存在则新增。)
            /// </summary>
            public static void SetConnectionStrings(IEnumerable<ConnectionStringSettings> connStringSettings, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                foreach (var item in connStringSettings)
                {
                    ConnectionStringSettings connStringSetting = config.ConnectionStrings.ConnectionStrings[item.Name];
                    if (connStringSetting != null)
                    {
                        connStringSetting.ConnectionString = item.ConnectionString;
                        connStringSetting.ProviderName = item.ProviderName;
                    }
                    else
                    {
                        config.ConnectionStrings.ConnectionStrings.Add(item);
                    }
                }
    
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("connectionStrings");
            }
    
            /// <summary>
            /// 删除连接字符串配置项
            /// </summary>
            public static void RemoveConnectionString(string name, string configPath = null)
            {
                var config = GetConfiguration(configPath);
                config.ConnectionStrings.ConnectionStrings.Remove(name);
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("connectionStrings");
            }
    
            /// <summary>
            /// 删除多个连接字符串配置项
            /// </summary>
            public static void RemoveConnectionStrings(string configPath = null, params string[] names)
            {
                var config = GetConfiguration(configPath);
                if (names != null)
                {
                    foreach (string name in names)
                    {
                        config.ConnectionStrings.ConnectionStrings.Remove(name);
                    }
                }
                else
                {
                    config.ConnectionStrings.ConnectionStrings.Clear();
                }
                config.Save(ConfigurationSaveMode.Modified);
                ConfigurationManager.RefreshSection("connectionStrings");
            }
        }
    View Code

        2、添加一个类,命名为MemoryCacheHelper(注意需引用System.Runtime.Caching.dll),代码如下:

        /// <summary>
        /// 内存缓存帮助类,支持绝对过期时间、滑动过期时间、文件依赖三种缓存方式。
        /// </summary>
        class MemoryCacheHelper
        {
            private static readonly object _locker1 = new object(), _locker2 = new object();
    
            /// <summary>
            /// 取缓存项,如果不存在则返回空。
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <returns></returns>
            public static T GetCacheItem<T>(string key)
            {
                try
                {
                    return (T)MemoryCache.Default[key];
                }
                catch
                {
                    return default(T);
                }
            }
    
            /// <summary>
            /// 是否包含指定键的缓存项
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public static bool Contains(string key)
            {
                return MemoryCache.Default.Contains(key);
            }
    
            /// <summary>
            /// 取缓存项,如果不存在则新增缓存项。
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="cachePopulate"></param>
            /// <param name="slidingExpiration"></param>
            /// <param name="absoluteExpiration"></param>
            /// <returns></returns>
            public static T GetOrAddCacheItem<T>(string key, Func<T> cachePopulate, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
            {
                if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
                if (cachePopulate == null) throw new ArgumentNullException("cachePopulate");
                if (slidingExpiration == null && absoluteExpiration == null) throw new ArgumentException("Either a sliding expiration or absolute must be provided");
    
                if (MemoryCache.Default[key] == null)
                {
                    lock (_locker1)
                    {
                        if (MemoryCache.Default[key] == null)
                        {
                            T cacheValue = cachePopulate();
                            if (!typeof(T).IsValueType && cacheValue == null)   //如果是引用类型且为NULL则不存缓存
                            {
                                return cacheValue;
                            }
    
                            var item = new CacheItem(key, cacheValue);
                            var policy = CreatePolicy(slidingExpiration, absoluteExpiration);
    
                            MemoryCache.Default.Add(item, policy);
                        }
                    }
                }
    
                return (T)MemoryCache.Default[key];
            }
    
            /// <summary>
            /// 取缓存项,如果不存在则新增缓存项。
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="cachePopulate"></param>
            /// <param name="dependencyFilePath"></param>
            /// <returns></returns>
            public static T GetOrAddCacheItem<T>(string key, Func<T> cachePopulate, string dependencyFilePath)
            {
                if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
                if (cachePopulate == null) throw new ArgumentNullException("cachePopulate");
    
                if (MemoryCache.Default[key] == null)
                {
                    lock (_locker2)
                    {
                        if (MemoryCache.Default[key] == null)
                        {
                            T cacheValue = cachePopulate();
                            if (!typeof(T).IsValueType && cacheValue == null)   //如果是引用类型且为NULL则不存缓存
                            {
                                return cacheValue;
                            }
    
                            var item = new CacheItem(key, cacheValue);
                            var policy = CreatePolicy(dependencyFilePath);
    
                            MemoryCache.Default.Add(item, policy);
                        }
                    }
                }
    
                return (T)MemoryCache.Default[key];
            }
    
            /// <summary>
            /// 指定缓存项的一组逐出和过期详细信息
            /// </summary>
            /// <param name="slidingExpiration"></param>
            /// <param name="absoluteExpiration"></param>
            /// <returns></returns>
            private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration)
            {
                var policy = new CacheItemPolicy();
    
                if (absoluteExpiration.HasValue)
                {
                    policy.AbsoluteExpiration = absoluteExpiration.Value;
                }
                else if (slidingExpiration.HasValue)
                {
                    policy.SlidingExpiration = slidingExpiration.Value;
                }
    
                policy.Priority = CacheItemPriority.Default;
    
                return policy;
            }
    
            /// <summary>
            /// 指定缓存项的一组逐出和过期详细信息
            /// </summary>
            /// <param name="filePath"></param>
            /// <returns></returns>
            private static CacheItemPolicy CreatePolicy(string filePath)
            {
                CacheItemPolicy policy = new CacheItemPolicy();
                policy.ChangeMonitors.Add(new HostFileChangeMonitor(new List<string>() { filePath }));
                policy.Priority = CacheItemPriority.Default;
                return policy;
            }
    
            /// <summary>
            /// 移除指定键的缓存项
            /// </summary>
            /// <param name="key"></param>
            public static void RemoveCacheItem(string key)
            {
                if (Contains(key))
                {
                    MemoryCache.Default.Remove(key);
                }
            }
        }
    View Code

        3、添加一个WinForm窗体,命名为Main,并添加一个按钮。

        4、配置App.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
      </startup>
      <connectionStrings>
        <add name ="connString" connectionString="server=.;database=db_test;uid=sa;pwd=********;" />
      </connectionStrings>
    </configuration>

        5、Main窗体代码如下:

            private void button1_Click(object sender, EventArgs e)
            {
                int times1 = 0, times2 = 0;
                for (int i = 0; i < 10; i++)
                {
                    if (MemoryCacheHelper.Contains("connString"))
                    {
                        times1++;
                    }
                    else
                    {
                        times2++;
                        string connstr = MemoryCacheHelper.GetOrAddCacheItem("connString", () =>
                        {
                            return ConfigHelper.GetConnectionString("connString", null);
                        }, Application.StartupPath + @"App.config");
                    }
                }
                MessageBox.Show($"内存缓存读取次数:{times1},非内存缓存读取次数:{times2}", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

        6、运行结果如下:

        参考自:

        https://www.cnblogs.com/mq0036/p/10312945.html

        https://www.cnblogs.com/zuowj/p/8366735.html

        https://www.cnblogs.com/zuowj/p/8440902.html

  • 相关阅读:
    IO多路复用
    Elasticsearch之打分机制、集群搭建、脑裂问题
    Elasticsearch之-映射管理,ik分词器
    Elasticsearch之高亮查询,聚合查询
    Elasticsearch之索引、文档、组合查询、排序查询、filter过滤操作
    Go 数组、切片、Maps
    Go if-else语句、for循环、switch语句
    Go 函数、包、mode模式
    毕业设计-1.05
    毕业设计-1.04
  • 原文地址:https://www.cnblogs.com/atomy/p/12372678.html
Copyright © 2020-2023  润新知