一、MVC缓存简介
缓存是将信息(数据或页面)放在内存中以避免频繁的数据库存储或执行整个页面的生命周期,直到缓存的信息过期或依赖变更才再次从数据库中读取数据或重新执行页面的生命周期。在系统优化过程中,缓存是比较普遍的优化做法和见效比较快的做法。
MVC缓存本质上还是.NET的一套缓存体系,只不过该缓存体系应用在了MVC框架上。下面的示例把缓存应用在MVC上。
缓存的常用场景:
数据被频繁的使用,并且很少发生变化或对即时性的要求不高。
二、Control 缓存
Control缓存即是把缓存应用到整个Control上,该Control下的所有Action都会被缓存起来。Control缓存的粒度比较粗,应用也比较少些。
namespace MvcCache.Controllers
{
[OutputCache(Duration = 10)]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.CurrentTime = System.DateTime.Now;
return View();
}
public ActionResult Index1()
{
ViewBag.CurrentTime = System.DateTime.Now;
return View();
}
}
}
在名为Control的Control中加入了OutputCache,并设置持续时间为10秒(Duration=10),即每10秒后过期当再次触发时更新缓存。下面是View中的代码,打印ViewBag的时间。
@{
ViewBag.Title = "Index";
}
<h2>@ViewBag.CurrentTime</h2>
@{
ViewBag.Title = "Index1";
}
<h2>@ViewBag.CurrentTime</h2>
一直刷新的情况~~~
三、Action 缓存
即把缓存用到Action上,Action缓存为比较常用的缓存方式,该方式粒度细一些。使用方法类似Control缓存。
public class HomeController : Controller
{
[OutputCache(Duration = 10)]
public ActionResult Index()
{
ViewBag.CurrentTime = System.DateTime.Now;
return View();
}
public ActionResult Index1()
{
ViewBag.CurrentTime = System.DateTime.Now;
return View();
}
}
四、使用配置文件
当我们需要将N个Control或Action加入缓存,并且缓存的参数是一致的情况下,我们可以把相关的设置放到Web.config中,并在程序中加入相应的配置。
<system.web>
<!--配置缓存-->
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="TestConfigCache" duration="10"/>
</outputCacheProfiles>
</outputCacheSettings>
</caching>
<!--配置缓存-->
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
</system.web>
配置缓存节只需要将其放在system.web节下即可,下面是使用的方法
public class HomeController : Controller
{
//TestConfigCache为在配置文件中配置的缓存节
[OutputCache(CacheProfile = "TestConfigCache")]
public ActionResult Index()
{
ViewBag.CurrentTime = System.DateTime.Now;
return View();
}
public ActionResult Index1()
{
ViewBag.CurrentTime = System.DateTime.Now;
return View();
}
}
注:当Control与Action都应用了缓存时,以Action的缓存为主。
五、OutPutCache 参数简介
下面代码为mvc4的OutputCache的定义
using System;
using System.Web.UI;
namespace System.Web.Mvc
{
// 摘要:
// 表示一个特性,该特性用于标记将缓存其输出的操作方法。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class OutputCacheAttribute : ActionFilterAttribute, IExceptionFilter
{
// 摘要:
// 初始化 System.Web.Mvc.OutputCacheAttribute 类的新实例。
public OutputCacheAttribute();
// 摘要:
// 获取或设置缓存配置文件名称。
//
// 返回结果:
// 缓存配置文件名称。
public string CacheProfile { get; set; }
//
// 摘要:
// 获取或设置子操作缓存。
//
// 返回结果:
// 子操作缓存。
public static System.Runtime.Caching.ObjectCache ChildActionCache { get; set; }
//
// 摘要:
// 获取或设置缓存持续时间(以秒为单位)。
//
// 返回结果:
// 缓存持续时间。
public int Duration { get; set; }
//
// 摘要:
// 获取或设置位置。
//
// 返回结果:
// 位置。
public OutputCacheLocation Location { get; set; }
//
// 摘要:
// 获取或设置一个值,该值指示是否存储缓存。
//
// 返回结果:
// 如果应存储缓存,则为 true;否则为 false。
public bool NoStore { get; set; }
//
// 摘要:
// 获取或设置 SQL 依赖项。
//
// 返回结果:
// SQL 依赖项。
public string SqlDependency { get; set; }
//
// 摘要:
// 获取或设置基于内容变化的编码。
//
// 返回结果:
// 基于内容变化的编码。
public string VaryByContentEncoding { get; set; }
//
// 摘要:
// 获取或设置基于自定义项变化的值。
//
// 返回结果:
// 基于自定义项变化的值。
public string VaryByCustom { get; set; }
//
// 摘要:
// 获取或设置基于标头变化的值。
//
// 返回结果:
// 基于标头变化的值。
public string VaryByHeader { get; set; }
//
// 摘要:
// 获取或设置基于参数变化的值。
//
// 返回结果:
// 基于参数变化的值。
public string VaryByParam { get; set; }
// 摘要:
// 返回一个值,该值指示子操作缓存否处于活动状态。
//
// 参数:
// controllerContext:
// 控制器上下文。
//
// 返回结果:
// 如果子操作缓存处于活动状态,则为 true;否则为 false。
public static bool IsChildActionCacheActive(ControllerContext controllerContext);
//
// 摘要:
// 此方法是 System.Web.Mvc.IActionFilter.OnActionExecuted(System.Web.Mvc.ActionExecutedContext)
// 的实现并支持 ASP.NET MVC 基础结构。它不应直接在您的代码中使用。
//
// 参数:
// filterContext:
// 筛选器上下文。
public override void OnActionExecuted(ActionExecutedContext filterContext);
//
// 摘要:
// 此方法是 System.Web.Mvc.IActionFilter.OnActionExecuting(System.Web.Mvc.ActionExecutingContext)
// 的实现并支持 ASP.NET MVC 基础结构。它不应直接在您的代码中使用。
//
// 参数:
// filterContext:
// 筛选器上下文。
public override void OnActionExecuting(ActionExecutingContext filterContext);
//
// 摘要:
// 此方法是 System.Web.Mvc.IExceptionFilter.OnException(System.Web.Mvc.ExceptionContext)
// 的实现并支持 ASP.NET MVC 基础结构。它不应直接在您的代码中使用。
//
// 参数:
// filterContext:
// 筛选器上下文。
public void OnException(ExceptionContext filterContext);
//
// 摘要:
// 此方法是 System.Web.Mvc.IResultFilter.OnResultExecuted(System.Web.Mvc.ResultExecutedContext)
// 的实现并支持 ASP.NET MVC 基础结构。它不应直接在您的代码中使用。
//
// 参数:
// filterContext:
// 筛选器上下文。
public override void OnResultExecuted(ResultExecutedContext filterContext);
//
// 摘要:
// 在操作结果执行之前调用。
//
// 参数:
// filterContext:
// 筛选器上下文,它封装有关使用 System.Web.Mvc.AuthorizeAttribute 的信息。
//
// 异常:
// System.ArgumentNullException:
// filterContext 参数为 null。
public override void OnResultExecuting(ResultExecutingContext filterContext);
}
}
常用属性:
1)CacheProfile:缓存使用的配置文件的缓存名称。
2)Duration:缓存时间,以秒为单位,这个除非你的Location=None,可以不添加此属性,其余时候都是必须的。
3)OutputCacheLocation:枚举类型,缓存的位置。当设置成None时,所有缓存将失效,默认为Any。
Any:页面被缓存在浏览器、代理服务器端和web服务器端;
Client:缓存在浏览器;
DownStream:页面被缓存在浏览器和任何的代理服务器端;
Server:页面被缓存在Web服务器端;
None:页面不缓存;
ServerAndClient:页面被缓存在浏览器和web服务器端;
4)VaryByParam:用于多个输出缓存的字符串列表,并以分号进行分隔。默认时,该字符串与GET方法传递的参数或与POST方法传递的变量相对应。当被设置为多个参数时,输出缓存将会为每个参数都准备一个与之相对应的文档版本。可能值包括none,*,以及任何有效的查询串或POST参数名称。
如果您不想要为不同的已缓存内容指定参数,可以将其设置为none。如果想要指定所有的已缓存内容参数,可以设置为*。
六、缓存依赖
111
SqlDependency:一个值,用于标识操作的输出缓存所依赖的一组数据库名称和表名称对。SqlCacheDependency 类在所有受支持的 SQL Server 版本 (7.0, 2000, 2005) 上监视特定的 SQL Server 数据库表,数据库表发生更改时,将自动删除缓存项,并向 Cache 中添加新版本的项。
概念理解起来很简单,主要是如何应用。下面为应用实例。示例说明:数据库为本地数据库,库名:wcfDemo(写wcf教程时用的库,懒了,直接用了),监听表名:user。缓存时间为:3600秒即一小时。数据库依赖周期为500毫秒,即每0.5秒监听下数据库是否有变化,如果有变化则立即更新缓存。
第一步:建立Control,测试代码如下:
public class SqlDependencyController : Controller
{
[OutputCache(CacheProfile = "SqlDependencyCache")]
public ActionResult Index()
{
ViewBag.CurrentTime = System.DateTime.Now;
return View();
}
//注册缓存依赖的服务代码:在vs命令行输入:aspnet_regsql -S localhost -U sa -P 123456 -ed -d wcfDemo -et -t user
//-S localhost:数据库地址
//-U sa:数据库登录名
//-P 123456:数据库登录密码
//-d wcfDemo:数据库的名称
//-t user:表名称(小写)
}
第二步,在配置文件中配置CacheProfile为SqlDependencyCache的节,并且配置缓存对数据库的依赖。
<configuration>
<!--数据库连接字符串-->
<connectionStrings>
<add name="Conn" connectionString="server=localhost;database=wcfDemo;uid=sa;pwd=123456;" providerName="System.Data.SqlClient"/>
</connectionStrings>
<!--数据库连接字符串-->
<appSettings>
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<system.web>
<!--配置缓存-->
<caching>
<outputCacheSettings>
<outputCacheProfiles>
<add name="TestConfigCache" duration="10"/>
</outputCacheProfiles>
</outputCacheSettings>
<sqlCacheDependency enabled="true" pollTime="2000"><!--缓存的数据库依赖节-->
<databases>
<add name="UserCacheDependency" connectionStringName="Conn" pollTime="500" />
<!--Conn:数据库连接字符串的名称,name随便启名,缓存节会用到-->
</databases>
</sqlCacheDependency>
</caching>
<!--配置缓存-->
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%Microsoft.NETFrameworkv4.0.30319aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%Microsoft.NETFramework64v4.0.30319aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers></system.webServer>
</configuration>
注意:
1)由于是缓存对数据库的依赖,此外必须包含connectionStrings的节。
2)<add name="UserCacheDependency" connectionStringName="Conn" pollTime="500"/>
connectionStringName:数据库连接字符串的名称
pollTime:监听数据库变化的周期,以毫秒为单位。即每500毫秒查看下数据库是否有变化。
3)<add name="SqlDependencyCache" duration="3600" sqlDependency="UserCacheDependency:user"/>
sqlDependency:数据依赖的节的名称+冒号+数据表名称(小写)。如果这个依赖会用到多个表,则用分号间隔开,如下所示UserCacheDependency:user;UserCacheDependency:user1
第三步:启用该数据库表的缓存依赖通知功能
打开vs命令工具行,输入:aspnet_regsql -S localhost -U sa -P 123456 -ed -d wcfDemo -et -t user
-S localhost:数据库地址
-U sa:数据库登录名
-P 123456:数据库登录密码
-d wcfDemo:数据库的名称
-t user:表名称(小写)
为只是监听是否发生数据变化,因此表结构随意,下面的我的表结构:
第四步:测试程序,上面的例子只打印了当前时间,如果不加入缓存依赖的情况下,1小时之内都应该运行出的结果都是当前时间,每次Ctrl+F5强制刷新浏览器时不发生任务变化。当加入缓存依赖后,只要对数据库的数据进行任意修改都会更新缓存的时间,即更改数据后再刷新浏览器时会看到时间在变化。
学习:MVC缓存 - 李林峰的园子