如何正确实现数据库的存储库级缓存

时间:2017-08-10 10:23:21

标签: c# caching

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

解决方案#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);
}

1 个答案:

答案 0 :(得分:0)

好吧,我不会说这里有严格的“正确”方式。您必须考虑每种设计的含义,并了解哪种更适合您的特定方案。

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

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