首页 新闻 搜索 专区 学院

EF的在MVC架构中数据缓存问题

0
悬赏园豆:50 [已关闭问题] 关闭于 2016-05-20 11:08

使用了EF4 + MVC3架构,因为数据库的数据变化不是很频繁而且数据量不是很大,在服务端缓存数据库的数据我觉得很有必要,本着简洁、有效的原则,于是写了个具有缓存性质的代码:

 

  1  public class DataService
  2     {
  3         public DataService() { }
  4 
  5         private T Get<T>(string cacheId, Func<T> getItemCallback, int secondsToCache) where T : class
  6         {
  7             T item = HttpRuntime.Cache.Get(cacheId) as T;
  8             if (item == null)
  9             {
 10                 item = getItemCallback();
 11                 HttpRuntime.Cache.Insert(cacheId,
 12                                          item,
 13                                          null,
 14                                          System.Web.Caching.Cache.NoAbsoluteExpiration,
 15                                          new TimeSpan(0, 0, secondsToCache),
 16                                          CacheItemPriority.Normal,
 17                                          null);
 18             }
 19             return item;
 20         }
 21 
 22         /// <summary>
 23         /// 使用谓词从数据库或数据缓存中获取对应的实体集合。
 24         /// </summary>
 25         /// <typeparam name="T">实体类型</typeparam>
 26         /// <param name="predicate">谓词表达式以进行筛选,若获取全部数据,可置为null,默认为null</param>
 27         /// <param name="fromDB">是否从数据库获取即时数据,默认为false</param>
 28         /// <returns>满足要求的数据集合</returns>
 29         public List<T> Get<T>(Expression<Func<T, bool>> predicate = null, bool fromDB = false, string path="") where T : class,new()
 30         {
 31             if (!fromDB)
 32             {
 33                 if (predicate == null)
 34                     return this.Get<List<T>>(typeof(T).Name, FecthFromDatabase<T>, 3600);
 35                 return this.Get<List<T>>(typeof(T).Name, FecthFromDatabase<T>, 3600).AsQueryable().Where<T>(predicate).ToList();
 36             }
 37             else
 38             {
 39                 this.Delete(typeof(T).Name);
 40                 if (predicate == null)
 41                     return new ServiceBase<T>().GetAll(path);
 42                 else
 43                     return new ServiceBase<T>().GetMuch(predicate, path);
 44             }
 45         }
 46 
 47         private List<T> FecthFromDatabase<T>() where T : class,new()
 48         {
 49             return new ServiceBase<T>().GetAll();
 50         }
 51 
 52         private void Delete(string cacheId)
 53         {
 54             HttpRuntime.Cache.Remove(cacheId);
 55         }
 56 
 57         /// <summary>
 58         /// 删除对应的实体,并更新该实体集合的缓存。
 59         /// </summary>
 60         /// <typeparam name="T"></typeparam>
 61         /// <param name="t">要删除的实体</param>
 62         public void Delete<T>(T t) where T : class,new()
 63         {
 64             new ServiceBase<T>().Delete(t);
 65             this.Delete(t.GetType().Name);
 66         }
 67 
 68 
 69        /// <summary>
 70        /// 删除满足谓词条件的实体集合,并更新该实体集合的缓存。
 71        /// </summary>
 72        /// <typeparam name="T"></typeparam>
 73        /// <param name="predicate">谓词表达式</param>
 74         public void Delete<T>(Expression<Func<T, bool>> predicate) where T : class,new()
 75         {
 76             new ServiceBase<T>().Delete(predicate);
 77             this.Delete(typeof(T).Name);
 78         }
 79 
 80         /// <summary>
 81         /// 更新对应的实体,并更新该实体集合的缓存。
 82         /// </summary>
 83         /// <typeparam name="T"></typeparam>
 84         /// <param name="t"></param>
 85         /// <returns>更新后的实体</returns>
 86         public T Update<T>(T t) where T : class,new()
 87         {
 88             T t2 = new ServiceBase<T>().Update(t);
 89             this.Delete(t.GetType().Name);
 90             return t2;
 91         }
 92 
 93         /// <summary>
 94         /// 插入一个实体,并更新该实体集合的缓存。
 95         /// </summary>
 96         /// <typeparam name="T"></typeparam>
 97         /// <param name="t"></param>
 98         /// <returns>插入后的实体</returns>
 99         public T Insert<T>(T t) where T : class,new()
100         {
101             T t2 = new ServiceBase<T>().Insert(t);
102             this.Delete(t.GetType().Name);
103             return t2;
104         }
105 
106     }

 

代码中ServiceBase是EF操作的一层封装,没贴出来。使用具体对象时只采取如下方法即可:

1 DataService db = new DataService();
2 //这里会自动缓存,或从缓存中得到数据
3 List<Order> orders = db.Get<Order>();
4 
5 Order order = orders.First();
6 order.Price = 2.03;
7 //缓存失效,下次会自动获取
8 db.Update<Order>(order);

 

对EF的理解不是很深刻,缓存到服务端的数据关系保存,比如Order里Product导航属性,使用缓存时Order的Product是空的,要想取到Product,只能通过Order的ProductId在Product集合中查找。

问题是:

1. 关于缓存,这样做是否科学?有没有更好的实践? 当然,这建立在一个前提下:数据量不大,数据更新不频繁。

2. 如何把Order的Product属性缓存下来,不至于使用那么复杂的方法来获取呢?

问题补充:

还有一个方法是基于Sql Server 2008的Broken,可以发通知到客户端,但经过试验,只要加入了一条新的数据到数据库,再打开页面速度那是相当的慢。

 

看来只能这么着结贴了。

Zigzag的主页 Zigzag | 初学一级 | 园豆:70
提问于:2012-11-16 23:24
< >
分享
所有回答(1)
0

缓存其实是个业务层处理的事情。

当读频率远大于写频率的时候,缓存其实很起作用。但是这个不是必需的准则

chenping2008 | 园豆:9836 (大侠五级) | 2012-11-17 19:40
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册