很好的问题,已经有两个很好的答案。起初我对此感到困惑,并想出了以下解决方案来解决问题,它将存储库封装在一个管理器中。管理器本身负责提取连接字符串并将其注入到存储库中。
我发现这种方法可以单独测试存储库,比如在模拟控制台应用程序中,要简单得多,而且我很幸运在几个大型项目中遵循这种模式。尽管我承认我不是测试、依赖注入或其他方面的专家!
我要问自己的主要问题是 DbService 是否应该是单例。我的理由是,不断创建和销毁封装在DbService 中的各种存储库并没有多大意义,而且由于它们都是无状态的,我认为允许它们“生存”没有太大问题。虽然这可能是完全无效的逻辑。
编辑:如果您想要一个现成的解决方案,请查看我在 GitHub 上的 Dapper 存储库实现
存储库管理器的结构如下:
/*
* Db Service
*/
public interface IDbService
{
ISomeRepo SomeRepo { get; }
}
public class DbService : IDbService
{
readonly string connStr;
ISomeRepo someRepo;
public DbService(string connStr)
{
this.connStr = connStr;
}
public ISomeRepo SomeRepo
{
get
{
if (someRepo == null)
{
someRepo = new SomeRepo(this.connStr);
}
return someRepo;
}
}
}
示例存储库的结构如下:
/*
* Mock Repo
*/
public interface ISomeRepo
{
IEnumerable<SomeModel> List();
}
public class SomeRepo : ISomeRepo
{
readonly string connStr;
public SomeRepo(string connStr)
{
this.connStr = connStr;
}
public IEnumerable<SomeModel> List()
{
//work to return list of SomeModel
}
}
连接起来:
/*
* Startup.cs
*/
public IConfigurationRoot Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
//...rest of services
services.AddSingleton<IDbService, DbService>();
//...rest of services
}
最后,使用它:
public SomeController : Controller
{
IDbService dbService;
public SomeController(IDbService dbService)
{
this.dbService = dbService;
}
public IActionResult Index()
{
return View(dbService.SomeRepo.List());
}
}