缓存模型的更好方法

时间:2016-07-26 06:44:36

标签: asp.net asp.net-mvc asp.net-mvc-5 dapper

我的简单存储库的getAll方法:

    public List<ListModel> GetAllLists()
    {
            using (MySqlConnection connection = new MySqlConnection(this.connectionString))
            {
                return connection.Query<ListModel>("SELECT * FROM projectx.lists").AsList();
            }

    }

我正在使用我在这里找到的这个类来处理缓存:

    public class CacheUtils : ICacheService
    {    
        public TValue Get<TValue>(string cacheKey, Func<TValue> getItemCallback, double durationInMinutes = 120) where TValue : class
        {

            TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
            if (item == null)
            {
                Debug.WriteLine("Not cached");
                item = getItemCallback();
                MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
            }
            else
                Debug.WriteLine("Cached!");
            return item;
        }

        public TValue Get<TValue, TId>(string cacheKeyFormat, TId id, Func<TId, TValue> getItemCallback, double durationInMinutes = 120) where TValue : class
        {

            string cacheKey = string.Format(cacheKeyFormat, id);
            TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
            if (item == null)
            {

                item = getItemCallback(id);
                MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
            }


            return item;
        }
    }

家庭控制器:

    public ActionResult Index()
    {
        ListRepository listRep = new ListRepository();
        CacheUtils cache = new CacheUtils();
        return View(cache.Get("lists", listRep.GetAllLists));
    }

问题,有没有比从控制器调用帮助器更好的处理缓存的方法?理想情况下,它应该在存储库方法中。但是,我是否需要在存储库的每个方法上重复检查现有缓存数据?即:

    public List<ListModel> GetAllLists()
    {
        var lists = Cache["lists"];
        if(lists == null)
        {
            using (MySqlConnection connection = new MySqlConnection(this.connectionString))
            {
                lists = connection.Query<ListModel>("SELECT * FROM projectx.lists").AsList();
            }

            Cache["lists"] = lists;
        }
        return ((List<ListModel>)lists);
    }

2 个答案:

答案 0 :(得分:1)

使用装饰器模式,不要使用缓存逻辑来判断业务或ui。 用ninject之类的东西(或者如果你不想添加DI那样糟糕的混蛋)我建议将它标记为单个实例。

好处包括:

  • 添加像void Save(ListModel)这样的无效方法很容易 使缓存无效。
  • 您的顶层和底层一无所知 关于他们被缓存的事实。
  • 您还可以再次装饰以添加日志记录,分析等
  • 您还可以控制缓存生命周期
  • 您没有使用缓存逻辑来控制控制器级别
  • 易于删除

所以像下面这样的东西会起作用。有关如何在ninject中添加装饰器,请参阅https://stackoverflow.com/a/8910599/1073280

json_last_error

意见:也许只是为了保持代码较小,但要小心使用带有ORM的select *。如果有人重命名或删除了一个列,你将无法轻松地进行单元测试/检测故障机制。

答案 1 :(得分:0)

在我看来,它不应该在存储库中,因为它(对我来说)闻起来像违规或SRP。缓存应该是存储库之上的更高级别的服务。

您需要考虑实际需要缓存的好处。如果缓存是为了加速WEB API接口,那么将它放在控制器中是最好的方法。如果您还需要在其他地方进行缓存,请考虑引入一些中间层服务类并将缓存放在那里,但我总是以某种方式使其成为可选项。