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");
}
}
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);
}
}
}
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 = , times2 = ;
for (int i = ; i < ; 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
C# MemoryCache学习笔记的更多相关文章
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- PHP-会员登录与注册例子解析-学习笔记
1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- JAVA GUI编程学习笔记目录
2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...
- seaJs学习笔记2 – seaJs组建库的使用
原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...
- CSS学习笔记
CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...
- HTML学习笔记
HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...
- DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记
今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...
随机推荐
- python 封装底层实现原理
事实上,python封装特性的实现纯属"投机取巧",之所以类对象无法直接调用私有方法和属性,是因为底层实现时,python偷偷改变了它们的名称. python在底层实现时,将它们的 ...
- eclipse android ndk开发遇到的问题.
1. error:parameter name omitted 用javah生成的.h文件中,方法是没有指定形参的,实现的时候需要我们在实现的方法定义中加上形参. 2. 'NewStringUTF' ...
- Processing 3!
Welcome to Processing 3! Dan explains the new features and changes; the links Dan mentions are on th ...
- 做.net的成为 微软mvp 是一个目标吧。
mvp 的评比 需要好多好多 绩效考核 比如博客排名,比如发表的文章数.
- Doxygen -- part 2
Documenting the code 这个章节涵盖两个主题: 如何在你的代码中放置注释, 一遍doxygen可以在生成的文档中囊括它们. 如何组织一个注释块的内容, 以使得输出美观. 特殊注释块 ...
- 《阿k学Python》一Python入门(一)
前言 各位看博客的园友们,大家好,我就是那个风流倜傥的KK,还记得我那篇2019年的年中总结博客吗?我想有许多看博客的园友是没有读过我那篇文章的,KK很生气,后果很严重(开个玩笑了,怎么可能).给大家 ...
- DFS(深度优先搜索遍历有向图)-03-有向图-太平洋大西洋水流问题
给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度.“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界. 规定水流只能按照上.下.左.右四个方向流动,且只能从高 ...
- 数据结构与算法 --- js描述栈
js描述栈及栈的使用 栈的特性就是只能通过一端访问,这一段就是叫做栈顶.咖啡馆内的一摞盘子就是最形象的栈的例子: 根据栈的特性,就可以定义栈的一些特殊属性和方法;用js的描述栈的时候底层数据结构用的是 ...
- PS-蒙版的深入解析
ps四大核心技术是什么?通道.蒙版.路径.选区 通道: 通道的详解,不过比较早的文章了. http://www.blueidea.com/tech/graph/2004/2056.asp PS通道快速 ...
- HDU_1035_水
http://acm.xidian.edu.cn/problem.php?id=1035 本来想用goto优化一下的,不知道什么情况,加了goto就wa了. #include<iostream& ...