【发布时间】:2021-11-08 05:27:37
【问题描述】:
我尝试在我的基础架构层中实现一个存储库。我不使用 dbContext 作为工作单元——而是每个 repo 方法都做并完成它的工作。我将在上面的一层中实现事务以将 repo 方法结合在一起。
在我的前世(不在 .NET Core 中)我的 repo 方法通常如下:
class MyRepo:IMyRepo
{
public void Save(MyObject p)
{
using(var ctx = new MyDbContext())
{
ctx.MyTable.Add( ...);
ctx.SaveChanges();
}
在酷炫的 Core 和 DI 世界中,我尝试按如下方式实现该方法:
方式 1 - 将 DbContextOptions 添加到 DI
class MyRepo : IMyRepo
{
private readonly DbContextOptions<MyDbContext> Options;
public MyRepo(DbContextOptions<MyDbContext> options)
{
Options = options;
}
public void Save(MyObject p)
{
using var ctx = new MyDbContext(this.Options);
...
方式 2 - 将 DbContextFactory 添加到 DI
class MyRepo:IMyRepo
{
private readonly DbContextFactory<MyDbContext> Factory;
public MyRepo(DbContextFactory<MyDbContext> factory)
{
Factory = factory;
}
public void Save(MyObject p)
{
using var ctx = Factory.CreateDbContext();
...
方式 3 - 将 DbContextPool 添加到 DI
class MyRepo:IMyRepo
{
private readonly DbContextPool<MyDbContext> Pool;
public MyRepo(DbContextPool<MyDbContext> pool)
{
Pool = pool;
}
public void Save(MyObject p)
{
using var ctx = Pool.GetCtxInstance(); ? ???
...
我想以两种方式对我的存储库进行单元测试:
- 在本地 .mdf 文件上,连接到它并执行真正的 sql 操作并检查它们的结果
- 我计划使用假存储库测试域服务。我读到有一种方法可以使用“内存表”来伪造存储库,在这种情况下,我认为我必须在测试期间以某种方式替换我的 DbContext 实例
我的问题:
- 第三种方式如何获取一个新的上下文实例(当使用pool时?)?还是像
ctx = new MyDbContext()这么简单? - 这是一个真实的例子来伪造 MyDbContext 本身,而不仅仅是改变它的“选项”?如何伪造它?为什么?
- 在这种情况下,我认为工厂是最好的,因为我可以实现其他方法来创建 dbcontext 以供以后测试。是吗?
- 那么,在存储库本身以及使用伪造存储库的域服务上执行单元测试的最佳方法是什么?
您对实施存储库有什么建议?提前致谢!
【问题讨论】:
-
对于实例化 DbContext,new() 总是创建新对象,这里没有池,也没有魔法。但是,如果您使用 AddDbContextPool 为特定 DbContext 注册了一个池,则可以通过 DI、构造函数注入或 ServiceProvider 从池中获取任何此类 DbContext。顺便说一句,如果您更喜欢工厂方法,还有
AddPooledDbContextFactory方法。 -
谢谢。那么需要第 4 种方式,应该在哪里提供 ServiceProvider 类并将其存储在 repo 中?
标签: c# dependency-injection entity-framework-core repository-pattern