在这篇博文中,我们将面对现实地将文件存储改为数据库存储。既然软件开发中不变的是变化本身,那我们主动求变,用变化来验证代码的设计是否能随机应变。
  之前使用文件存储的架构是这样的:
  Presentation层-WebAPI:CNBlogsRefreshTokenProvider
  Application层-接口:IRefreshTokenService
  Application层-实现:RefreshTokenService
  Domain层-实体:RefreshToken
  Repository层-接口:IRefreshTokenRepository
  Repository层-实现:FileStorage.RefreshTokenRepository
  依赖关系是这样的:
  Presentation层的CNBlogsRefreshTokenProvider -> Application层的接口IRefreshTokenService + Domain层的实体RefreshToken。
  Application层的实现RefreshTokenService -> Repository层的接口IRefreshTokenRepository + Domain层的实体RefreshToken。
  Repository层的实现FileStorage.RefreshTokenRepository -> Domain层的实体RefreshToken。
  对于这样的分层架构,要将文件存储改为数据库存储,看上去似乎很简单——只需基于数据库存储,使用相应的ORM工具(比如EF),实现IRefreshTokenRepository接口,然后将之注入,其它地方无需更改1行代码。
  当我们悠哉悠哉地去写IRefreshTokenRepository接口的实现Database.RefreshTokenRepository的代码时,突然发现有些不对劲。
  之前基于文件存储的FireStorage.RefreshTokenRepository的代码是这么实现的(为了简化问题,我们只看查询部分的实现):
public class RefreshTokenRepository : IRefreshTokenRepository
{
private List<RefreshToken> _refreshTokens;
public RefreshTokenRepository()
{
//...
}
public async Task<RefreshToken> FindById(string Id)
{
return _refreshTokens.Where(x => x.Id == Id).FirstOrDefault();
}
}
  现在基于Entity Framework写Database.RrefreshTokenRepository的实现代码时,也要写同样的LINQ查询代码(下面代码中的加粗部分):
public class RefreshTokenRepository : IRefreshTokenRepository
{
public RefreshTokenRepository()
{
}
public async Task<RefreshToken> FindById(string Id)
{
using (var context = new OpenApiDbContext())
{
return context.Set<RefreshToken>()
.Where(x => x.Id == Id).FirstOrDefault();
}
}
}