泛型仓储结合装饰器模式实现缓存的最佳实践咨询
泛型仓储+缓存的最佳实践(针对特定方法缓存)
核心思路
不用纠结VS自动生成的所有接口方法,大部分方法直接委托给原始仓储实现即可,只对需要缓存的方法做定制处理——这才是装饰器模式的核心:只增强需要的功能,其余逻辑完全复用原有实现。
具体实现步骤
编写CachedBlogRepository装饰器
实现IBlogRepository,注入原始BlogRepository和IMemoryCache。不需要缓存的方法直接调用原始仓储的对应逻辑;仅在GetBlogsByCreatorAsync中添加缓存逻辑。示例代码:
public class CachedBlogRepository : IBlogRepository { private readonly IBlogRepository _originalRepo; private readonly IMemoryCache _cache; private const string _cacheKeyPrefix = "Blogs_Creator_"; public CachedBlogRepository(IBlogRepository originalRepo, IMemoryCache cache) { _originalRepo = originalRepo; _cache = cache; } // 无需缓存的方法,直接转发给原始仓储 public Task<Blog> GetBlogByIdAsync(int id) { return _originalRepo.GetBlogByIdAsync(id); } public async Task AddBlogAsync(Blog blog) { // 关键:增删改操作要清理对应缓存,避免数据不一致 _cache.Remove(_cacheKeyPrefix + blog.CreatorId); await _originalRepo.AddBlogAsync(blog); } // 仅对该方法做缓存处理 public async Task<IEnumerable<Blog>> GetBlogsByCreatorAsync(int creatorId) { var cacheKey = _cacheKeyPrefix + creatorId; return await _cache.GetOrCreateAsync(cacheKey, async entry => { // 设置缓存过期策略,比如10分钟自动失效 entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10); // 缓存不存在时,从原始仓储获取数据 return await _originalRepo.GetBlogsByCreatorAsync(creatorId); }); } // 其他自动生成的接口方法,全部直接转发给_originalRepo即可 // 比如:public Task UpdateBlogAsync(Blog blog) => _originalRepo.UpdateBlogAsync(blog); // ... }依赖注入配置
在DI容器中先注册原始仓储,再用装饰器包装它,确保上层调用拿到的是带缓存的实例:// 注册原始仓储 services.AddScoped<IBlogRepository, BlogRepository>(); // 用装饰器包装(部分DI框架自带Decorate方法,比如Microsoft.Extensions.DependencyInjection) services.Decorate<IBlogRepository, CachedBlogRepository>(); // 如果没有Decorate方法,手动注册方式: // services.AddScoped<IBlogRepository>(sp => // new CachedBlogRepository(sp.GetRequiredService<BlogRepository>(), sp.GetRequiredService<IMemoryCache>()));缓存一致性维护
执行博客的增、删、改操作时,必须清理对应作者的缓存(比如示例中AddBlogAsync里的缓存移除操作),防止缓存数据与数据库不一致。
为什么这是最佳实践?
- 符合单一职责原则:原始仓储只负责数据访问,装饰器只专注缓存增强,职责完全分离。
- 对上层透明:业务代码无需修改,依然依赖
IBlogRepository,完全感知不到缓存的存在。 - 扩展性强:后续要给其他方法加缓存,只需在装饰器中修改对应方法,不用动原始仓储代码。
内容的提问来源于stack exchange,提问作者totesz09
相关产品推荐
相关产品推荐

