很多情況下需要用到緩存,合理利用緩存一方面可以提高程式的響應速度,同時可以減少對特定資源訪問的壓力。為了避免每次請求都去訪問後臺的 資源(例如資料庫),一般會考慮將一些更新不是很頻繁的、可以重用的數據,通過一定的方式臨時地保存起來,後續的請求根據情況可以直接訪問這 些保存起來的數據,這種機制就是所謂 ...
很多情況下需要用到緩存,合理利用緩存一方面可以提高程式的響應速度,同時可以減少對特定資源訪問的壓力。為了避免每次請求都去訪問後臺的
資源(例如資料庫),一般會考慮將一些更新不是很頻繁的、可以重用的數據,通過一定的方式臨時地保存起來,後續的請求根據情況可以直接訪問這
些保存起來的數據,這種機制就是所謂的緩存機制。
.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