为什么要注入整个 DbContext 而不是只注入必要的 DbSet?

Why inject the entire DbContext instead of just the necessary DbSets?

我看过很多项目是否将整个DbContext注入一个class:

public class MyClass
{
    public MyClass(MyDbContext context)
    {
        ...
    }
    
    public void DoStuff()
    {
         dbContext.MyTable.Select(x => x...)
    }
}

为什么不这样做:

public class MyClass
{
    public MyClass(DbSet<MyType> myTypes)
    {
        ...
    }
    
    public void DoStuff()
    {
         myTypes.Select(x => x...)
    }
}

我发现#2 更清楚地说明了对象究竟需要操作哪些数据。它使单元测试特别清晰,因为从构造函数中可以明显看出依赖关系。否则,您必须检查该方法的实现以找出它究竟需要哪些数据,以便您可以正确设置测试。

那么为什么#1 是常态?

(P.S。抱歉标签不好,但标签系统似乎已损坏 atm)

通常开发人员编写单元测试来测试业务用例,数据访问层不应包含任何逻辑,这就是为什么人们使用 Repository Pattern 来隐藏数据访问层的实现。

Otherwise, you have to inspect the implementation of the method to find out what data it needs exactly so you can setup your test properly.

MyDbContextDbSet<MyType> 与数据访问有关,当您尝试对 DoStuff 方法执行单元测试时,您不应考虑执行查询来编写测试和您唯一需要做的就是模拟 MyDbContextDbSet<MyType>。此外,当使用具体 class 作为依赖项时,您违反了 Dependency Inversion Principle,这就是为什么您必须查看 DoStuff 方法的实现以找出哪些数据以及数据来自何处.

因为“保存”在 dbcontext 上,而不是在子集合上。

"SaveChangesAsync" 作为最重要的一个。但下面列出了其他人。

        int saveChangesAsyncValue = await this.myDbContext.SaveChangesAsync(token);

框架:

https://docs.microsoft.com/en-us/dotnet/api/system.data.entity.dbcontext.savechangesasync?view=entity-framework-6.2.0

核心:

https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.savechangesasync?view=efcore-5.0

其他(核心):

https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontext.savechanges?view=efcore-5.0

您应该真正专注于对业务逻辑进行单元测试。巧妙地,这也意味着。

  1. 停止将(任何)业务逻辑放入数据层。 (和它的亲戚,停止将业务逻辑放在您的表示层中)。

您应该将数据层的(模拟)注入到您的业务逻辑中 类。

话虽如此,EF InMemoryDatabase 稍微模糊了界限。

但这并不能避免必须有可用的“myDbContext”。