2017-08-10 68 views
0

实现数据库级缓存的正确方法是什么? (这不是缓存提供商,它是关于缓存和存储库之间的关系!)如何正确实现数据库级缓存

解决方案#1:注入外部简单缓存

public class MyRepository : IMyRepository 
{ 
    private readonly IDataCache _dataCache; 

    public MyRepository(IDataCache dataCache) 
    { 
     _dataCache = dataCache; 
    } 

    public string Get(int id) 
    { 
     var result = _dataCache.Get(id) as string; 

     if (result == null) 
     { 
      //Go fetch data from data source 
      _dataCache.Add(id, result); 
     } 

     return result; 
    } 
} 

解决方案#2:其它CachedRepository类实现相同的接口 (这将需要一些时髦的DI配置正确解决,但它是可能的)

public class MyRepository : IMyRepository 
{ 
    private readonly IDataCache _dataCache; 

    public MyRepository(IDataCache dataCache) 
    { 
     _dataCache = dataCache; 
    } 

    public string Get(int id) 
    { 
     //Go fetch data from data source 
     return result; 
    } 
} 

public class CachedMyRepository : IMyRepository 
{ 
    private readonly IMyRepository _myRepository; 
    private readonly IDataCache _dataCache; 

    public CachedMyRepository(IMyRepository myRepository, IDataCache dataCache) 
    { 
     _dataCache = dataCache; 
     _myRepository = myRepository; 
    } 

    public string Get(int id) 
    { 
     var result = _dataCache.Get(id) as string; 

     if (result == null) 
     { 
      result = _myRepository.Get(id); 
      _dataCache.Add(id, result); 
     } 

     return result; 
    } 
} 

(每种解决方案都基于这个简单的存储库和高速缓存接口为了讨论)

public interface IMyRepository 
{ 
    string Get(int id); 
} 

public interface IDataCache 
{ 
    object Get(object key); 
    void Add(object key, object item); 
} 
+0

你缓存一些永远不会改变其状态的对象吗?你什么时候使缓存无效?从IDataCache接口看来,我从来没有喜欢过我。 –

+0

Mc Kevin。你错过了这一点。这不是关于缓存实现,这是关于存储库和缓存之间的关系。请阅读该问题。 –

+0

解决方案2对我来说更好,我认为您在解决方案2的MyRepository中不需要IDataCache。 –

回答

0

那么,我不会说这里有严格的“正确”方式。你必须考虑每个设计的含义,看看哪些更适合你的特定场景。

第一个选项使您的存储库在概念上成为一个缓存存储库,因为它需要一个IDataCache才能工作(至少,这就是设计所暗示的)。您可以使用空对象模式来支持打开和关闭缓存。如果测试对你来说是一个重要的考虑因素,那么在这种情况下,你需要使用某种测试加倍,或者你可以一起测试版本库和数据缓存。

第二个选项基本上是装饰模式(除了你不需要IDataCache到MyRepository中 - 我认为这是由于复制粘贴)。它使您的存储库完全无视任何缓存逻辑。可以动态添加和删除缓存,还可以使用其他类型的修饰器来扩充您的存储库(例如,您可以添加日志记录)。至于测试 - 您可以按原样测试您的存储库,而无需进行任何测试。

+0

解决方案#1 - 让我们假设没有要求打开或关闭缓存,它只是一直开着。 解决方案#2 - IDataCache被抽象化的原因是为了让单元测试它而不暴露一堆东西,并且允许CachedRepository/Repository的实例是transient/scoped而不是singleton。 –