MVC缓存02,使用数据层缓存,添加或修改时让缓存失效
在"MVC缓存01,使用控制器缓存或数据层缓存"中,在数据层中可以设置缓存的有效时间。但这个还不够"智能",常常希望在编辑或创建的时候使缓存失效,加载新的数据。
□ 思路
1、缓存是以键值<string, object>存放的,在创建缓存的时候,先把IDictionary<int,T>作为缓存内容存储,int为T的主键。
2、EF上下文保存的时候时候把变化保存到数据库,并更新缓存中的内容。
● 先找出上下文中状态为added或modified的实体:var changeobjects
● 把变化保存数据到数据库:context.SaveChanges()
● 根据缓存key获取类型为IDictionary<int,T>的缓存内容:var cacheData = Cache.Get("vehicles") as Dictionary<int, Vehicle>;
● 最后遍历这些变化的实体,更新缓存项:cacheData[vehicle.Id] = vehicle;
□ 缓存接口
public interface ICacheProvider
{
object Get(string key);
void Set(string key, object data, int cacheTime);
bool IsSet(string key);
void Invalidate(string key);
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ 缓存接口实现
围绕using System.Runtime.Caching的MemoryCache.Default返回类型为ObjectCache的缓存属性实现缓存接口:获取缓存项、设置缓存、判断是否设置缓存、清空缓存。
using System;
using System.Runtime.Caching;
namespace MvcApplication1.Cache
{
public class DefaultCacheProvider : ICacheProvider
{
private ObjectCache Cache
{
get { return MemoryCache.Default; }
}
public object Get(string key)
{
return Cache[key];
}
public void Set(string key, object data, int cacheTime)
{
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(cacheTime);
Cache.Add(new CacheItem(key, data), policy);
}
public bool IsSet(string key)
{
return (Cache[key] != null);
}
public void Invalidate(string key)
{
Cache.Remove(key);
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ Model
public partial class Vehicle
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ 针对Vehicle的Repositoy接口:
using System.Collections.Generic;
using MvcApplication1.Models;
namespace MvcApplication1.Repository
{
public interface IVehicleRepository
{
void ClearCache();
IEnumerable<Vehicle> GetVehicles();
void Insert(Vehicle vehicle);
void Update(Vehicle vehicle);
void SaveChanges();
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ 针对Vehicle的Repositoy接口实现:
using System.Collections.Generic;
using System.Data;
using System.Data.Entity.Infrastructure;
using System.Linq;
using MvcApplication1.Cache;
using MvcApplication1.Models;
namespace MvcApplication1.Repository
{
public class VehicleRepository : IVehicleRepository
{
protected DemoEntities DataContext { get; private set; }
public ICacheProvider Cache { get; set; }
public VehicleRepository() : this(new DefaultCacheProvider())
{
}
public VehicleRepository(ICacheProvider cacheProvider)
{
this.DataContext = new DemoEntities();
this.Cache = cacheProvider;
}
public void ClearCache()
{
Cache.Invalidate("vehicles");
}
public System.Collections.Generic.IEnumerable<Models.Vehicle> GetVehicles()
{
var vehicles = Cache.Get("vehicles") as IDictionary<int, Vehicle>;
if (vehicles == null)
{
vehicles = DataContext.Vehicle.ToDictionary(v => v.Id);
if (vehicles.Any())
{
Cache.Set("vehicles",vehicles,30);
}
}
return vehicles.Values;
}
public void Update(Vehicle vehicle)
{
if (vehicle != null)
{
DataContext.Set<Vehicle>().Attach(vehicle);
DataContext.Entry(vehicle).State = EntityState.Modified;
}
}
public void Insert(Vehicle vehicle)
{
DataContext.Set<Vehicle>().Add(vehicle);
}
public void SaveChanges()
{
//获取上下文中EntityState状态为added或modified的Vehicle
var changeobjects = DataContext.ChangeTracker.Entries<Vehicle>();
//把变化保存到数据库
DataContext.SaveChanges();
//更新缓存中相关的Vehicle
var cacheData = Cache.Get("vehicles") as Dictionary<int, Vehicle>;
if (cacheData != null)
{
foreach (var item in changeobjects)
{
var vehicle = item.Entity as Vehicle;
cacheData[vehicle.Id] = vehicle;
}
}
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
在保存缓存Cache.Set("vehicles",vehicles,30)之前,把从上下文获取到的数据转换成IDictionary<int,T>类型vehicles = DataContext.Vehicle.ToDictionary(v => v.Id);
□ HomeController
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MvcApplication1.Models;
using MvcApplication1.Repository;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public IVehicleRepository Repository { get; set; }
public HomeController(IVehicleRepository repository)
{
this.Repository = repository;
}
public HomeController() : this(new VehicleRepository())
{
}
public ActionResult Index()
{
return View(Repository.GetVehicles());
}
[HttpPost]
public ActionResult Index(FormCollection form)
{
Repository.ClearCache();
return RedirectToAction("Index");
}
public ActionResult Edit(int id)
{
var vehicle = Repository.GetVehicles().Single(v => v.Id == id);
return View(vehicle);
}
[HttpPost]
public ActionResult Edit(Vehicle vehicle)
{
Repository.Update(vehicle);
Repository.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult Create()
{
return View(new Vehicle());
}
[HttpPost]
public ActionResult Create(Vehicle vehicle)
{
Repository.Insert(vehicle);
Repository.SaveChanges();
return RedirectToAction("Index");
}
}
}
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ Home/Index.cshtml
@model IEnumerable<MvcApplication1.Models.Vehicle>
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<style type="text/css">
table td {
border-collapse: collapse;
border: solid 1px black;
}
</style>
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<th>编号</th>
<th>车型</th>
<th>价格</th>
<th></th>
</tr>
@foreach (var vehicle in Model)
{
<tr>
<td>@vehicle.Id.ToString()</td>
<td>@vehicle.Name</td>
<td>@string.Format("{0:c}",vehicle.Price)</td>
<td>
@Html.ActionLink("编辑", "Edit", new { id=vehicle.Id })
</td>
</tr>
}
</table>
@using (Html.BeginForm())
{
<input type="submit" value="使缓存失效重新获取数据库数据" id="InvalidButton" name="InvalidButton"/>
}
<p>
@Html.ActionLink("创建", "Create")
</p>
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
□ Home/Create.cshtml
展开@model MvcApplication1.Models.Vehicle
@{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Vehicle</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
□ Home/Edit.cshtml
展开@model MvcApplication1.Models.Vehicle
@{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Vehicle</legend>
@Html.HiddenFor(model => model.Id)
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Price)
@Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
□ 结果:
创建或修改之前:
编辑更新:
创建:
编辑创建成功后:
□ 参考资料
※ DATA CACHING WITH .NET 4.0 AND ASP.NET MVC – PART 2
MVC缓存02,使用数据层缓存,添加或修改时让缓存失效的更多相关文章
- MVC缓存,使用数据层缓存,添加或修改时让缓存失效
在"MVC缓存01,运用控制器缓存或数据层缓存"中,在数据层中可以设置缓存的有用时刻.但这个还不够"智能",常常期望在修改或创立的时分使缓存失效,加载新的数据. ...
- spring mvc 的jpa JpaRepository数据层 访问方式汇总
本文转载至:http://perfy315.iteye.com/blog/1460226 AppleFramework在数据访问控制层采用了Spring Data作为这一层的解决方案,下面就对Spri ...
- mvc EF 从数据库更新实体,添加视图实体时添加不上的问题
视图对象没有一列为非null的,解决办法,在视图中,将某一列排除为null的可能,比如:isnull(te,1),即可.
- XML中 添加或修改时 xmlns="" 怎么删除
//创建节点时 记得加上 ---> xmldoc.DocumentElement.NamespaceURI XmlElement url = xmldoc.CreateElement(&quo ...
- [开源]OSharpNS 步步为营系列 - 2. 添加业务数据层
什么是OSharp OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架.这个 ...
- Caffe实现多标签输入,添加数据层(data layer)
因为之前遇到了sequence learning问题(CRNN),里面涉及到一张图对应多个标签.Caffe源码本身是不支持多类标签数据的输入的. 如果之前习惯调用脚本create_imagenet.s ...
- php yaf框架扩展实践五——数据层
从狭义角度上来理解数据层就是数据库,比较广义的理解来看数据库.远程数据.文件等都可以看做数据层.项目初期的时候一般单一的数据库就可以了,随着流量的增大就要对数据层做很多的改进,例如增加从库分散读压力, ...
- MVC缓存01,使用控制器缓存或数据层缓存
对一些浏览频次多.数据量大的数据,使用缓存会比较好,而对一些浏览频次低,或内容因用户不同的,不太适合使用缓存. 在控制器层面,MVC为我们提供了OutputCacheAttribute特性:在数据 ...
- [NewLife.XCode]数据层缓存(网站性能翻10倍)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...
随机推荐
- [转载]Web 研发模式演变
原文链接:https://github.com/lifesinger/blog/issues/184 前不久徐飞写了一篇很好的文章:Web 应用的组件化开发.本文尝试从历史发展角度,说说各种研发模式的 ...
- JQGrid 参数、属性API
JQGrid是一个在jquery基础上做的一个表格控件,以ajax的方式和服务器端通信. JQGrid Demo 是一个在线的演示项目.在这里,可以知道jqgrid可以做什么事情. 下面是转自其他人b ...
- Linux下ffmpeg的各种编解码器的安装
首先要安装各种解码器 1.lame tar -zxvf lame- cd lame- ./configure --enable-shared make make install 2.libogg ...
- NDK学习三: 纯手工编译Hello World
1.配置环境变量 添加make工具path环境变量: E:\Android\android-ndk-r10b\prebuilt\windows-x86_64\bin 2.编写Hello W ...
- (转)Do not use "using" for WCF Clients - 不要将WCF Client 放在 ‘Using’ 代码块中
RT,最近在编写WCF的应用程序,发现WCF client在关闭的时候有可能会抛出异常,经过搜索之后,发些小伙伴们也遇到过类似的问题,遂记载下来,以备自身和其他小伙伴查看. 原文链接:http://w ...
- 《oracle每日一练》oracle截取字符的函数
转载 在Oracle中 可以使用instr函数对某个字符串进行判断,判断其是否含有指定的字符. 在一个字符串中查找指定的字符,返回被查找到的指定的字符的位置. 语法: instr(sourceStri ...
- 在asp.net mvc中上传大文件
在asp.net mvc 页面里上传大文件到服务器端,需要如下步骤: 1. 在Control类里添加get 和 post 方法 // get method public ActionResult Up ...
- Ubuntu里面软件的安装与卸载
在Ubuntu里面,有时候碰到软件配置错了,这是重新再安装的话,会检测到已安装,系统不会再重新安装,就需要卸载之后重装 1.通过deb包安装的情况: 安装.deb包: 代码:sudo dpkg -i ...
- linux资源使用配置文件 /etc/security/limits.conf和ulimit
limits.conf文件实际上是linux PAM中pam_limits.so的配置文件,而且只针对于单个会话. limits.conf的格式如下: <domain> <type& ...
- c#简易计算器
微软MSDN的代码库就有示例 http://code.msdn.microsoft.com/Simple-Calculator-54ec8e4a using System; using System. ...