zoukankan      html  css  js  c++  java
  • MVC缓存02,使用数据层缓存,添加或修改时让缓存失效

    在"MVC缓存01,使用控制器缓存或数据层缓存"中,在数据层中可以设置缓存的有效时间。但这个还不够"智能",常常希望在编辑或创建的时候使缓存失效,加载新的数据。

    □ 思路

    1、缓存是以键值<string, object>存放的,在创建缓存的时候,先把IDictionary<int,T>作为缓存内容存储,int为T的主键。
    14

    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);
        }

    □ 缓存接口实现

    围绕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);
            }
        }
    }
     

    □ Model

        public partial class Vehicle
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public decimal Price { get; set; }
        }

    □ 针对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();
        }
    }
     

    □ 针对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;
                    }
                }
            }
        }
    }
     

    在保存缓存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");
            }
        }
    }
     

    □ 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>
     

    □ Home/Create.cshtml

    展开

    □ Home/Edit.cshtml

    展开

     

    □ 结果:

    创建或修改之前:
    10

     

    编辑更新:
    11

     

    创建:
    12

     

    编辑创建成功后:
    13

     

    □ 参考资料
    DATA CACHING WITH .NET 4.0 AND ASP.NET MVC – PART 2

  • 相关阅读:
    HTML的BODY内标签介绍
    前端HTML基础和head部分
    pymysql模块
    数据库基础五
    数据库基础四
    数据库基础三
    数据库基础二
    数据库基础一
    洛谷P5055 可持久化文艺平衡树 (可持久化treap)
    BZOJ
  • 原文地址:https://www.cnblogs.com/darrenji/p/3649994.html
Copyright © 2011-2022 走看看