实现数据库级别缓存的正确方法是什么? (这不是关于缓存提供者,它是关于缓存和存储库之间的关系!)
解决方案#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 :(得分:0)
好吧,我不会说这里有严格的“正确”方式。您必须考虑每种设计的含义,并了解哪种更适合您的特定方案。
第一个选项使您的存储库在概念上成为缓存存储库,因为它需要IDataCache才能工作(至少,这就是设计所暗示的)。您可以使用Null对象模式来支持打开和关闭缓存。如果测试对您来说是一个重要的考虑因素,那么在这种情况下,您需要使用某种类型的测试双,或者您可以一起测试存储库和数据缓存。
第二个选项本质上是Decorator模式(除了你不需要IDataCache到MyRepository中 - 我认为这是由于复制粘贴)。它使您的存储库完全忘记任何缓存逻辑。有可能动态添加和删除缓存,您还可以使用其他类型的装饰器扩充您的存储库(例如,您可以添加日志记录)。至于测试 - 你可以按原样测试你的存储库,没有任何测试双打。