在"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,使用数据层缓存,添加或修改时让缓存失效的更多相关文章

  1. MVC缓存,使用数据层缓存,添加或修改时让缓存失效

    在"MVC缓存01,运用控制器缓存或数据层缓存"中,在数据层中可以设置缓存的有用时刻.但这个还不够"智能",常常期望在修改或创立的时分使缓存失效,加载新的数据. ...

  2. spring mvc 的jpa JpaRepository数据层 访问方式汇总

    本文转载至:http://perfy315.iteye.com/blog/1460226 AppleFramework在数据访问控制层采用了Spring Data作为这一层的解决方案,下面就对Spri ...

  3. mvc EF 从数据库更新实体,添加视图实体时添加不上的问题

    视图对象没有一列为非null的,解决办法,在视图中,将某一列排除为null的可能,比如:isnull(te,1),即可.

  4. XML中 添加或修改时 xmlns="" 怎么删除

    //创建节点时 记得加上  ---> xmldoc.DocumentElement.NamespaceURI XmlElement url = xmldoc.CreateElement(&quo ...

  5. [开源]OSharpNS 步步为营系列 - 2. 添加业务数据层

    什么是OSharp OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架.这个 ...

  6. Caffe实现多标签输入,添加数据层(data layer)

    因为之前遇到了sequence learning问题(CRNN),里面涉及到一张图对应多个标签.Caffe源码本身是不支持多类标签数据的输入的. 如果之前习惯调用脚本create_imagenet.s ...

  7. php yaf框架扩展实践五——数据层

    从狭义角度上来理解数据层就是数据库,比较广义的理解来看数据库.远程数据.文件等都可以看做数据层.项目初期的时候一般单一的数据库就可以了,随着流量的增大就要对数据层做很多的改进,例如增加从库分散读压力, ...

  8. MVC缓存01,使用控制器缓存或数据层缓存

    对一些浏览频次多.数据量大的数据,使用缓存会比较好,而对一些浏览频次低,或内容因用户不同的,不太适合使用缓存.   在控制器层面,MVC为我们提供了OutputCacheAttribute特性:在数据 ...

  9. [NewLife.XCode]数据层缓存(网站性能翻10倍)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...

随机推荐

  1. 跟着百度学PHP[4]OOP面对对象编程-12-抽象类

    什么是抽象方法?我们在类里面定义的没有方法体的方法就是抽象方法.所谓的没有方法体指的是,在方法声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名后加上分号结束,另外在声明抽象方法时还要加一个 ...

  2. C++内存分配方式

    参考:http://www.cnblogs.com/daocaoren/archive/2011/06/29/2092957.html http://www.cnblogs.com/skydesign ...

  3. vmware vcenter orchestrator configuration提示“用户名密码错误或登录失败超过次数被锁定”

    首次登录,使用默认用户密码登录vmware/vmware vmware vcenter orchestrator configuration提示"用户名密码错误或登录失败超过次数被锁定&qu ...

  4. tinyhttp源码阅读(注释)

    这里就不细述了,代码很简单. 其实现的功能比较若,可以做一个参考. 因为其通过文件的权限位来判断是否是一个CGI脚本,所以在权限位不对的情况下会判断不正确.例如我将这个目录放置在NTFS分区,所有的文 ...

  5. 1 python学习——python环境配置

    1 python学习--python环境配置 要学习python语言,光看书看教程还是不好,得动手去写.当然,不管学习什么编程语言,最佳的方式还在于实践. 要实践,先得有一个Python解释器来解释执 ...

  6. Mysql5.7版本编译安装及配置

    配置yum安装方式 1.配置本地yum源 vim /etc/yum.repos.d/rhel-source.repo [rhel-source] name=Red Hat Enterprise Lin ...

  7. python查找并删除相同文件-UNIQ File-script版本

    今天用wxPython做了一个GUI程序,实现查找指定目录内的相同文件,主要原理是计算文件的md5值(计算前先找出文件大小相同的文件,然后计算这些文件的md5值,而不是所有文件都计算,大大减少了md5 ...

  8. 仿QQ侧滑菜单<大自然的搬运工-代码不是我的>

    1.记录下效果图 2.二个工具类 package myapplication.com.myapplicationfortest.utils; import android.util.Log; /** ...

  9. PHP的反射类ReflectionClass、ReflectionMethod使用实例

    PHP5 具有完整的反射API,添加对类.接口.函数.方法和扩展进行反向工程的能力. 反射是什么? 它是指在PHP运行状态中,扩展分析PHP程序,导出或提取出关于类.方法.属性.参数等的详细信息,包括 ...

  10. MYSQL 的错误Incorrect information in file: '.\test\stuff.frm

    用eos 重新数据库初始化 会出现这个错误 然后 把 mysql 的 两个日志文件删除就行.第一次不知道怎么g搞,花了一下午的时间重装了mysql.5.0. 删除文件 >>>> ...